I've following code which I compile with gcc
#include<stdio.h>
#include<stdbool.h>
#define true 9
int main() {
printf("TRUE = %d\n",true);
return 0;
}
And I get Error
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
But when I alter the code a bit
#include<stdio.h>
#define true 9
#include<stdbool.h>
int main() {
printf("TRUE = %d\n",true);
return 0;
}
Output:
TRUE = 1
Question:
I understand the reason for error in first case but In second case when I define true
before I #include<stdbool.h>
, why is it allowed to redefine true
?
Update:
Here is stdbool.h.
First few lines are
#ifndef _STDBOOL_H
#define _STDBOOL_H
#ifndef __cplusplus
#define bool _Bool
#define true 1
#define false 0
which is nothing like in the Yu Hao 's answer .
In the file stdbool.h
, the code may look like this:
#ifdef true
#undef true
#define true 1
#endif
You should do the same when the macro may be defined before. Another similar trick is like this:
#ifndef MAGIC
#define MAGIC 42
#endif
EDIT
Turns out this is gcc's feature, see @alk's answer for detail.
All warnings, other than those generated by ‘#warning’, are suppressed while GCC is processing a system header. Macros defined in a system header are immune to a few warnings wherever they are expanded.
Although Yu Hao gave a possible answer to the question, things indeed are different here.
This easily could be proved by looking into stdbool.h
to realise that there is no #ifdef ... #endif
"guard" around the definition of true
.
Moreover gcc does simply surpress warnings that whould be given for issues in system headers*1.
Use the gcc's option -isystem
to make the 1st example behave like the 2nd.
From the gcc manual:
The header files declaring interfaces to the operating system and runtime libraries often cannot be written in strictly conforming C. Therefore, GCC gives code found in system headers special treatment. All warnings, other than those generated by ‘#warning’ (see Diagnostics), are suppressed while GCC is processing a system header. Macros defined in a system header are immune to a few warnings wherever they are expanded. This immunity is granted on an ad-hoc basis, when we find that a warning generates lots of false positives because of code in macros defined in system headers.
[...]
The -isystem command line option adds its argument to the list of directories to search for headers, just like -I. Any headers found in that directory will be considered system headers.
*1: System headers are headers included in <>
brackets.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With