Why does the preprocessor interpret the word "linux" as the constant "1"?

Question:

Original question: Why does the C preprocessor interpret the word "linux" as the constant "1"? by ahmedaly50

Why does the preprocessor in GCC interpret the word linux as the constant 1 ?

test.c

#include <stdio.h>
int main(void)
{
int linux = 5;
return 0;
}

Result of $ gcc -E test.c (for after pre-processor stage):

int main(void)
{
int 1 = 5;
return 0;
}

Which, of course, produces an error.

(BTW: There is no #define linux in the stdio.h file)

Answer:

Compiling C and C ++ programs is not a simple step, that is, the source code is accepted as input and the executable is output. In reality, the compiler is just one piece (albeit the main piece) of a process that starts with the preprocessor, continues with the compiler itself, and ends with the linker . This chain of programs is often called, for short, toolchain , since they are precisely a chain of tools that is triggered to finally generate an executable program. This is, by the way, the working philosophy in UNIX, so that small tools solve relatively simple problems, and their concatenation ends up generating a result that can be as complex as an executable program. Inside this chain, the CPP preprocessor defines a series of macros that are available before compiling anything. These are the so-called predefined macros.

These macros help in the compilation process (for example, __FILE__ always has the name of the file they are compiling), others help to know what the purpose of the compilation is ( __STDC__ worth one if you are compiling standard C).

Over time, these macros became so popular that everyone used them, and thus they became standardized. Thus, there are some predefined macros that, for example, every toolchain for C must have. During the standardization process, it was concluded that it was best if these macros were preceded, as well as followed, by double underlines. For example, the macro linux became __linux__ . This way, the user would never mistakenly choose the name of a predefined macro, which would lead to problems like the one you describe.

The macro linux , as well as unix was used as an aid to know for which system it was being compiled. Over time, they began to be transformed according to what the standard indicated, but they remain in the default compilation to serve those old programs that still have the presence of these macros to be compiled correctly.

To know the predefined macros, you can invoke cpp ( C Pre-Processor , the C preprocessor, nothing to do with C ++) with the -dM options (important to respect upper and lower case) so that it lists all the macros by default. Since you don't want to contribute a file, you can do it with /dev/null .

$ cpp -dM /dev/null
#define __unix__ 1
#define __linux__ 1
#define unix 1
#define linux 1
#define __x86_64 1
...

Among many others, on my machine (Ubuntu 15.10 x64) the macros that identify it as linux, as a variant (POSIX standard) of unix, and as a 64-bit architecture are defined. A) Yes…

$ cpp -dM /dev/null | grep linux
#define __linux 1
#define __linux__ 1
#define __gnu_linux__ 1
#define linux 1

With grep we can filter the result so that only macros that have the word linux as their identifier or part of their identifier appear. We see that they are all, the old and the new.

What if we tell CPP that we want to compile for a C standard, such as 1999?

$ cpp -dM /dev/null -std=c99 | grep linux
#define __linux 1
#define __linux__ 1
#define __gnu_linux__ 1

As we have asked CPP to be more strict, only the predefined macros that are actually part of the standard appear.

The standard predefined macros as well as the CPP- specific predefined macros are documented in the preprocessor manual .

Hope this answers your question.

Scroll to Top