C中的#define和#include顺序

The*_*ect 10 c gcc include c-preprocessor

我遵循我编译的代码 gcc

#include<stdio.h>
#include<stdbool.h>
#define true 9
int main() { 
   printf("TRUE = %d\n",true);
   return 0;
}
Run Code Online (Sandbox Code Playgroud)

我得到错误

test.c:3:0: warning: "true" redefined [enabled by default]
In file included from test.c:2:0:
/usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdbool.h:34:0: note: this is the location of the previous definition
Run Code Online (Sandbox Code Playgroud)

但是当我改变代码时

#include<stdio.h>
#define true 9
#include<stdbool.h>
int main() { 
   printf("TRUE = %d\n",true);
   return 0;
}
Run Code Online (Sandbox Code Playgroud)

输出:

TRUE = 1
Run Code Online (Sandbox Code Playgroud)

题:

我在第一种情况下理解错误的原因但在第二种情况下,当我true在我之前定义时#include<stdbool.h>,为什么允许重新定义true

更新:

这是stdbool.h.

前几行是

#ifndef _STDBOOL_H
#define _STDBOOL_H

#ifndef __cplusplus

#define bool    _Bool
#define true    1
#define false   0
Run Code Online (Sandbox Code Playgroud)

这与余浩的回答完全不同.

Yu *_*Hao 9

在文件中stdbool.h,代码可能如下所示:

#ifdef true
#undef true
#define true 1
#endif
Run Code Online (Sandbox Code Playgroud)

在以前定义宏时,您应该这样做.另一个类似的技巧是这样的:

#ifndef MAGIC
#define MAGIC 42
#endif
Run Code Online (Sandbox Code Playgroud)

编辑

原来这是gcc的功能,请参阅@alk的详细解答.

除了'#warning'生成的警告之外,所有警告都会在GCC处理系统标头时被抑制.系统标题中定义的宏在任何扩展的位置都不受几个警告的影响.

  • 好吧,它必须是`#ifdef`然后是`#undef`,因为在第二个例子中,来自`stdbool.h`的值被打印而不是手工`#define`. (2认同)
  • "*......代码可能看起来像......*":但它没有.请看我对这个问题的回答. (2认同)

alk*_*alk 7

虽然余浩对这个问题给出了可能的答案,但事情确实有所不同.

这很容易通过研究stdbool.h来认识到#ifdef ... #endif围绕定义没有"保护" true.

此外,gcc确实只是为了解决系统头文件中的问题而提出的警告*1.

使用gcc的选项-isystem使第一个示例表现得像第二个.

从gcc手册:

声明操作系统和运行时库接口的头文件通常不能严格符合C语言编写.因此,GCC会在系统头文件中给出代码特殊处理.GCC处理系统标题时,除"#warning"(参见"诊断")生成的警告之外的所有警告都将被禁止.系统标题中定义的宏在任何扩展的位置都不受几个警告的影响.当我们发现警告由于系统头中定义的宏中的代码而产生大量误报时,会临时授予此免疫权.

[...]

-isystem命令行选项将其参数添加到目录列表以搜索标头,就像-I一样.在该目录中找到的任何标头都将被视为系统标头.


*1:系统标题是<>括号中包含的标题.