在C语言中,#define和#include的顺序是什么?

11

我有以下代码,我使用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

这与Yu Hao的答案完全不同。


5
我希望你并没有认真考虑定义“真”。 - Bathsheba
3
我认为OP正在进行测试,所以他需要一个不同于“1”的值来查看哪个宏正在起作用。 - Yu Hao
3个回答

9
在文件 stdbool.h 中,代码可能会像这样:
#ifdef true
#undef true
#define true 1
#endif

当宏可能在之前被定义时,您应该执行相同的操作。另一个类似的技巧是这样的:
#ifndef MAGIC
#define MAGIC 42
#endif

编辑

事实证明这是gcc的特性,详见@alk的回答

在GCC处理系统头文件时,除了“#warning”生成的警告之外的所有警告都会被抑制。在系统头文件中定义的宏在扩展到任何地方时都不会受到某些警告的影响。


2
那么,应该是 #ifdef 然后是 #undef,因为在第二个示例中打印的是 stdbool.h 的值,而不是手动的 #define - svk
2
"...代码可能看起来像......":但实际上并不是这样的。请查看我在这个问题上的答案。 - alk

7
尽管Yu Hao给出了一个可能的答案,但事实上这里确实有所不同。
通过查看stdbool.h可以证明这一点,因为在true的定义周围没有#ifdef ... #endif "守卫"。
此外,gcc只是简单地压制了在系统头文件中出现的问题的警告*1
使用gcc的选项-isystem使第一个示例的行为类似于第二个示例。 来自gcc手册: 声明操作系统和运行时库接口的头文件通常不能以严格符合C标准的方式编写。因此,GCC会对系统头文件中的代码进行特殊处理。在GCC处理系统头文件时,除了由“#warning”(参见诊断)生成的警告之外,所有警告都会被抑制。在系统头文件中定义的宏展开时,这些宏免受某些警告的影响。当我们发现警告因系统头文件中定义的宏中的代码而产生大量误报时,我们会基于特定情况豁免这些宏的警告。
命令行选项-isystem将其参数添加到搜索头文件的目录列表中,就像-I一样。该目录中找到的任何头文件将被视为系统头文件。

*1:系统头文件是用<>括起来的头文件。


嗯,“-isystem” 在我的“gcc”中似乎没有生成警告,但是+1,这是一个更好的解释。 - Shafik Yaghmour
@ShafikYaghmour:抱歉,我搞混了。请看我的更正答案。 - alk
@alk 因为“GCC对系统头文件中的代码给予特殊处理”,所以抑制警告不会导致错误。 - TheKojuEffect
@TheKojuEffect:是的。但请注意,这种“特殊处理”并不是指错误,而仅仅是指警告。 - alk

-1

好的,你的警告已经说得很清楚了:

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

GCC 允许您重新定义值,除非您明确告诉它不要这样做。您可以使用 -Werror 来实现此目的。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接