#c #preprocessor
#c #препроцессор
Вопрос:
Создайте файл /usr/local/include/define_x.h
с помощью одной строки:
#define X "/usr/local/include"
Следующая программа foo.cpp
компилируется и работает нормально без каких-либо предупреждений:
#include <iostream>
#define X "local"
#include <define_x.h>
int main()
{
std::cout << "X = " << X << std::endl;
return 0;
}
Вывод: X = /usr/local/include
Теперь поменяйте местами строки 3 и 4:
#include <iostream>
#include <define_x.h>
#define X "local"
int main()
{
std::cout << "X = " << X << std::endl;
return 0;
}
Теперь результат X = local
соответствует ожидаемому, но теперь появляется предупреждение компилятора:
foo.cpp:4: warning: "X" redefined
#define X "local"
In file included from foo.cpp:3:
/usr/local/include/define_x.h:1: note: this is the location of the previous definition
#define X "/usr/local/include"
Вопрос: Почему в первой версии нет предупреждения?
Оба были скомпилированы с помощью gcc 8.2.1: g foo.cpp
.
Похоже, это как-то связано с размещением файлов в стандартных каталогах /usr/include или / usr/local/include, поскольку их размещение либо в текущем каталоге, либо в другом, найденном через -I
, не дает такого эффекта.
Комментарии:
1. просто дикое предположение: возможно ли, что ваши параметры компилятора имеют
-isystem
? Это может объяснить, почему не генерируется предупреждение в зависимости от того, откуда включен файл2. извините, что пропустил.
g foo.cpp
..
Ответ №1:
Системные заголовочные файлы часто не могут быть записаны на строго соответствующем C. Они могут изменять некоторые макросы препроцессора несколько раз, как в этом примере:
#define FOO 0
#ifdef BAR
#define FOO 1
#endif
Было бы неприятно получать предупреждение обо всех этих изменениях. Поэтому предупреждение не выдается для системных заголовочных файлов.
Ваша строка кода
#include <define_x.h>
объявляет файл заголовка системным файлом заголовка. Вы должны получить другой результат, если используете
#include "define_x.h"
Комментарии:
1. Вы должны получить другой результат, если используете … — Я пробовал это, и я этого не делаю. А вы?
2. Из вашей первой ссылки: «Заголовочные файлы, объявляющие интерфейсы к операционной системе и библиотекам времени выполнения, часто не могут быть записаны в строго соответствующем C. Поэтому GCC предоставляет коду, содержащемуся в системных заголовках, особую обработку». — Спасибо, это та информация, которую я искал.