Включенные файлы из стандартных каталогов могут автоматически заменять существующие макросы?

#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 предоставляет коду, содержащемуся в системных заголовках, особую обработку». — Спасибо, это та информация, которую я искал.