#define и #include порядок в C
У меня есть код, который я компилирую с помощью gcc
#include<stdio.h>
#include<stdbool.h>
#define true 9
int main() {
printf("TRUE = %d\n",true);
return 0;
}
И я получаю 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
Но когда я немного изменяю код
#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
?
Update:
Вот stdbool.h.
Первые несколько строк
#ifndef _STDBOOL_H
#define _STDBOOL_H
#ifndef __cplusplus
#define bool _Bool
#define true 1
#define false 0
который не похож на ответ Yu Hao .
Ответы
Ответ 1
Хотя Ю Хао дал возможный ответ на вопрос, здесь действительно разные.
Это легко доказать, посмотрев на stdbool.h
, чтобы понять, что в определении true
нет #ifdef ... #endif
"защитника".
Кроме того, gcc просто прикладывает внимание к предупреждениям, которые должны быть заданы для проблем в заголовках системы * 1.
Используйте опцию gcc -isystem
, чтобы сделать первый пример, как 2-й.
Из руководства gcc:
Заголовочные файлы, объявляющие интерфейсы для операционной системы и библиотек времени выполнения, часто не могут быть записаны в строго соответствии C. Поэтому GCC дает код, найденный в специальной обработке системных заголовков. Все предупреждения, кроме тех, которые генерируются с помощью '#warning (см. Диагностика), подавляются, а GCC обрабатывает системный заголовок. Макросы, определенные в системном заголовке, защищены от нескольких предупреждений, где бы они ни расширялись. Этот иммунитет предоставляется на разовой основе, когда мы обнаруживаем, что предупреждение генерирует множество ложных срабатываний из-за кода в макросах, определенных в заголовках системы.
[...]
Опция командной строки -системы добавляет свой аргумент в список каталогов для поиска заголовков, как -I. Все заголовки, найденные в этом каталоге, будут считаться заголовками системы.
* 1: Заголовки систем - это заголовки, включенные в скобки <>
.
Ответ 2
В файле stdbool.h
код может выглядеть следующим образом:
#ifdef true
#undef true
#define true 1
#endif
Вы должны сделать то же самое, когда макрос может быть определен ранее. Другой подобный трюк выглядит следующим образом:
#ifndef MAGIC
#define MAGIC 42
#endif
ИЗМЕНИТЬ
Оказывается, это функция gcc, см. @alk answer для подробностей.
Все предупреждения, кроме тех, которые генерируются '#warning, подавляются, а GCC обрабатывает системный заголовок. Макросы, определенные в системном заголовке, не защищены от нескольких предупреждений, где бы они ни расширялись.
Ответ 3
Хорошо, ваше предупреждение уже говорит об этом:
test.c:3:0: warning: "true" redefined [enabled by default]
GCC позволяет вам переопределять значения, если вы явно не указали это. Вы можете использовать -Werror для этого.