Кросс-файл #if и #endif — это должно быть законно?

Согласно стандарту C11,

Директива предварительной обработки вида

# включить новую строку «q-char-sequence»

вызывает замену этой директивы всем содержимым исходного файла, идентифицируемого указанной последовательностью между «разделителями».

Так что, если у меня есть файл заголовка test.h содержащий:

#endif

И исходный файл test.c содержащий:

#if 1
#include "test.h"

Не должен ли он пройти этап предварительной обработки в соответствии со стандартом путем замены содержимого test.h на месте?

Но я не могу сделать это с clang, который говорит:

In file included from test.c:2:
./test.h:1:2: error: #endif without #if
#endif
^
test.c:1:2: error: unterminated conditional directive
#if 1
^
2 errors generated.

Так что же такое поведение, указанное в стандарте?

3

Решение

Если вы читаете, например, это C ++ #include ссылка включенный файл сначала запускается этапы перевода от одного до четырех и фаза четвертая работает препроцессор (рекурсивно).

Это означает, что файл, который вы включаете, должен быть заполнен #if а также #endif,

Это происходит и в Си.


После прочтения спецификации C11 (ISO / IEC 9899: 2011 [2012]), что я считать бывает это:

Компилятор находится в фазе препроцессора (фаза 4) и оценивает #if 1 директива препроцессора. Условие оценивается как истинное, поэтому оно входит в блок внутри условия. Есть песня #include "test.h" директивы.

Когда компилятор обрабатывает директиву include, он временно прекращает обработку текущего файла для обработки включенного файла. Эта обработка включенного файла проходит фазу компиляции с 1 по 4 (включительно) перед продолжением работы с текущим исходным файлом.

Когда обработка включенного файла заголовка переходит к фазе 4 и начинается обработка #endif директива, то не идет вверх в стеке рекурсивного включения, чтобы найти соответствующий #ifпрепроцессор просматривает только текущий кадр стека (текущий файл). Поэтому вы получаете первую ошибку о нет #if, Стандарт на самом деле ничего не говорит об этом. Все это говорит, в основном, что это #if должен иметь соответствующий #endif, То, что компилятор не идет вверх по стеку включения, чтобы найти соответствие #if кажется, больше деталей реализации.

В любом случае, препроцессор заканчивает обработку файла заголовка с шага 3 на этапе 4, который

В конце этого этапа все директивы препроцессора удаляются из источника.

Поэтому, когда элемент управления возвращается к предварительной обработке исходного файла, файл, который он фактически включает, не содержит никаких директив предварительной обработки. Все, что включено, это в основном пустой файл. И это приводит ко второй ошибке, что нет #endif для #ifпотому что там действительно нет.

6

Другие решения

clang правильно: такой раскол #if/#endif в разных файлах не соответствует. Это потому, что препроцессор сначала сканирует остальную часть файла, чтобы найти соответствующий #endif и только затем разрешает другие директивы препроцессора, которые присутствуют в условной части, которая сохраняется.

Это раздел 6.10.1 p6 стандарта C.

0

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector