C中的#define和#include顺序

时间:2013-09-23 11:34:09

标签: c gcc include c-preprocessor

我遵循使用gcc

编译的代码
#include<stdio.h>
#include<stdbool.h>
#define true 9
int main() { 
   printf("TRUE = %d\n",true);
   return 0;
}

我得到错误

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

但是当我改变代码时

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

输出:

TRUE = 1

问题:

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

更新

这是stdbool.h

前几行是

#ifndef _STDBOOL_H
#define _STDBOOL_H

#ifndef __cplusplus

#define bool    _Bool
#define true    1
#define false   0

这与余浩的answer完全不同。

3 个答案:

答案 0 :(得分:9)

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

#ifdef true
#undef true
#define true 1
#endif

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

#ifndef MAGIC
#define MAGIC 42
#endif

修改

原来这是gcc's feature,有关详细信息,请参阅@alk's answer

  

GCC正在处理系统标题时,将禁止除“#warning”生成的警告以外的所有警告。系统标题中定义的宏在任何扩展的地方都不会受到一些警告的影响。

答案 1 :(得分:7)

尽管Yu Hao给了问题possible answer,但事情确实有所不同。

通过调查stdbool.h以了解#ifdef ... #endif的定义周围没有true“警卫”,可以很容易地证明这一点。

此外,gcc会简单地抑制系统标题 * 1 中的问题。

使用gcc的选项-isystem使第一个示例的行为与第二个相同。

From the gcc manual:

  

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

     

[...]

     

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


* 1:系统标头是<>括号中包含的标头。

答案 2 :(得分:-1)

嗯,你的警告已经说明了:

test.c:3:0: warning: "true" redefined [enabled by default]

GCC允许您重新定义值,除非您明确告诉它不要。你可以使用-Werror。