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 the pre-processor stage):
int main(void)
{
int 1 = 5;
return 0;
}
Which of course produces an error.
(BTW: There is no one #define linux
in the stdio.h file)
The compilation of C and C++ programs is not a simple stage, that is, the source code is accepted as input and the executable is issued as 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 a toolchain for short., since they are precisely a chain of tools that are 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. Within this chain, the CPP preprocessor , defines a series of macros that are available before anything is compiled. These are the so-called predefined macros.
These macros help in the compilation process (for example,
__FILE__
it always takes the name of the file that is being compiled), others help to know what the objective of the compilation is (__STDC__
it is worth one if you are compiling standard C).Over time, these macros became so popular that everyone used them, and so 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 underscores. For example, the macro
linux
happened to be__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 asunix
was used to help figure out what system it was being compiled for. 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 options
-dM
(it is important to respect 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
.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. So...
With
grep
we can filter the result so that only and exclusively the macros that have the word as identifier or part of their identifier appearlinux
. We see that they are all, the old ones and the new ones.What happens if we tell CPP that we want to compile to a C standard, such as 1999?
Since 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 CPP 's own predefined macros are documented in the preprocessor manual .
I hope this answers your question.