The purpose of this blog is to help web developers to jump into systems programming. So you can ask any questions; there are no dummy questions. I want this blog to be a discussion space for every programmer who lives this journey.


I was hacking today at work, and I needed to define the CPU architecture of the machine at some point.

Then I typed “c++ os module” on google, hoping I’ll find an equivalent of the node:os module in Node.Js.

I was stunned to find out that my lovely os.arch() (or process.arch) has no equivalent on C++.

A few queries later, I found it. My answer has a name: “pre-processor”!

✅ What you’ll be able to do at the end of this article?

  • Determine the architecture of the current machine in C++
  • Basic understanding of pre-processor and a few directives

What is a pre-processor?

Pre-processor happens before compilation, and it will examine the code and will resolve directives within the code. The most known is the include directive:

Includes other source file into current source file at the line immediately after the directive.

Source: https://en.cppreference.com/w/cpp/preprocessor/include

What is a directive?

A directive is a statement that starts with a # followed by an instruction. The pre-processor will execute the instruction before compilation. Let’s take an example by defining a macro:

#define MAX_SIZE 30

if (size > MAX_SIZE) {
...
}

Define a macro with the “define” directiveAfter the pre-processor step, the code looks like this:

if (size > 30) {
...
}

For our use case, the pre-processor directive we need is “conditional inclusion”. It allows you to include or not a part of the code.

Let’s write an example where we want to warn the user conditionally.

// Display an error message if MAX\_SIZE is not defined

#ifndef MAX_SIZE
std::cerr << "MAX_SIZE is not defined" << std::endl;
#endif

“We seem far away from the CPU architecture definition, my boy!”.

Yeah, indeed! I’ll add my last ingredient to the recipe: the predefined macros!

Pre-defined macros for CPU architecture

As I said above, there is no built-in function to get the CPU architecture. But compilers bring pre-defined macros:

C and C++ compilers automatically define certain macros that can be used to check for compiler or operating system features. This is useful when writing portable software.

Pre-defined Compiler Macros / Wiki / Home!

There is a specific category that will help us: “architectures”:

Pre-defined Compiler Macros / Wiki / Architectures

Question: Is the fact that macros are defined by compilers the reason why we don’t have something exposed in the standard library? I’ll try to figure out this and answer it later!

Now we can imagine using these macros to define the CPU architecture. Let’s try it!

Example of defining CPU architecture with directives

Then I’ll use the __arm__, __aarch64__ & __x86_64__ macros to define an arch variable of type std::string:

// Define CPU architecture in C++ with pre-processor

#if defined(__arm__)
  std::string arch = "arm";
#elif defined(__aarch64__)
  std::string arch = "arm64";
#elif defined(__x86_64__)
  std::string arch = "x64";
#else
  std::string arch = "unknown";
#endif

I only handle a few cases here, but you can expand it as much as you want.

If we summarize a bit, we know:

  • we could use a pre-processor directive to change the code at compile time
  • we can use predefined macros shipped by compilers to determine the CPU architecture

Takeaways

If you want to read more about pre-processor and macros: