<span style="font-size:14px;"> #ifdef __linux
…
#endif
#ifdef _WINDOWS
…
#endif</span>
但查遍整个工程代码却没有找到在哪儿定义过他们。
今天仔细研究了一下,原来他们是由操作系统或是编译器定义的。以下将以__linux为例简要说明一下。
例如我们平常编译程序使用gcc,那么在gcc中就定义了__linux宏。
$gcc -dM -E - < /dev/null | grep -w "__linux"
#define__linux 1
补充:
简要分析一下命令。我使用的gcc版本是Ubuntu 4.4.3-4ubuntu5.1,在man手册中对-dM有说明:
-dCHARS
CHARS is a sequence of one or more of the following characters, and mustnot be preceded
by a space. Other characters areinterpreted by the compiler proper, or reserved for future
versions of GCC, and so are silently ignored. If you specify characters whose behavior
conflicts, the result is undefined.
M Instead of the normal output, generate a list of #define directives for all the macros
defined during the execution ofthe preprocessor, including predefined macros.
This gives you a way of finding out what is predefined in your version of the
preprocessor. Assuming you have no file foo.h, the command
touch foo.h; cpp -dM foo.h
will show all the predefined macros.
If you use -dM without the -E option, -dM is interpreted as a synonymfor -fdump-rtl-mach.
英语不是很好,中文意思大致如下:
-dCHARS
CHARS是下面的一个或多个字符一系列的组合,在-d与字符组合间不能以空格隔开。其他的字符由
编译器做出合适的解释,或是为了以后的GCC版本保留,因此这些保留字符会被默默地忽略。如果你
指定的某些字符所对应的行为存在冲突,执行结果将是未知的。
M 输出一份预处理器执行期间预处理器定义的宏,以及所检测到的使用#define指令定义的所有宏
的清单,替代正常的标准输出。这给了你一个得知当前版本预处理器定义了哪些宏的途径。假设
你没有foo.h这个文件,这条命令
touch foo.h; cpp -dM foo.h
将会显示预处理器所定义的所有宏。
如果你使用-dM但未指定-E选项,-dM会被解释为-fdump-rtl-mach的同义词。
-E选项告诉编译器只进行预处理,不进行之后的编译与连接。
-E选项后面的“- < /dev/null”代表用/dev/null作为标准输入传递给gcc。
因为/dev/null是空文件,所以其中也就没有任何的宏定义,那么“gcc -dM -E - < /dev/null”显示的也
就是gcc所定义所有宏定义。之后的grep是精确匹配出包含__linux的宏定义。