Что касается синтаксического анализа директив препроцессора, стандарт C99 (и стандарт C89 до него) четко определял последовательность операций, логически выполняемых компилятором. В частности, я считаю, что это означает, что этот код:
/* */ # /* */ include /* */ <stdio.h> /* */
эквивалентно:
#include <stdio.h>
Хорошо это или плохо, но GCC 3.4.4 с '-std = c89 -pedantic', в любом случае, принимает строку с комментариями. Я не защищаю это как стиль - ни на секунду (это ужасно). Я просто думаю, что это возможно.
В разделе 5.1.1.2 «Фазы перевода» ИСО / МЭК 9899: 1999 говорится:
[Сопоставление символов, включая триграфы]
[Соединение строк - удаление новой строки с обратной косой чертой]
Исходный файл разбивается на токены предварительной обработки и последовательности символов пробела (включая комментарии). Исходный файл не должен заканчиваться токеном частичной предварительной обработки или частичным комментарием. Каждый комментарий заменяется одним пробелом. Символы новой строки сохраняются. Будет ли каждая непустая последовательность символов пробела, кроме новой строки, сохраняться или заменяться одним символом пробела, определяется реализацией.
Выполняются директивы предварительной обработки, расширяются вызовы макросов, [...]
Раздел 6.10 Директивы предварительной обработки говорит:
Директива предварительной обработки состоит из последовательности токенов предварительной обработки, которая начинается с токена предварительной обработки #, который (в начале фазы трансляции 4) является либо первым символом в исходном файле (необязательно после пробела, не содержащего символов новой строки), либо которым следует за пробелом, содержащим хотя бы один символ новой строки, и заканчивается следующим символом новой строки.
Единственный возможный спор - это выражение в скобках «(в начале фазы 4 перевода)», которое может означать, что комментарии перед хешем должны отсутствовать, поскольку в противном случае они не заменяются пробелами до конца фазы 4.
Как отмечали другие, предварительные стандартные препроцессоры C не вели себя единообразно во многих отношениях, а пробелы перед и в директивах препроцессора были одной из областей, где разные компиляторы делали разные вещи, в том числе не распознавали директивы препроцессора с пробелами перед ними. .
Примечательно, что удаление обратной косой черты и новой строки происходит до анализа комментариев. Следовательно, не следует заканчивать //
комментарии обратной косой чертой.
#ifdef
строк в тех частях, где у меня есть реальный код. Вместо этого, если мне нужны условные вещи, я либо помещаю их в факторизованные функции, либо извлекаю макросы; так я нахожу намного яснее (ну, по крайней мере, для меня). В идеале все эти разложенные части будут в других файлах (заголовках или условно скомпилированных исходных файлах; обычным «условием» является то, для какой платформы создается код).В приведенном вами примере может быть уместно использовать отступ, чтобы сделать его более понятным, поскольку у вас такая сложная структура вложенных директив.
Лично я считаю, что большую часть времени полезно держать их без отступов, потому что эти директивы работают отдельно от остального кода. Такие директивы, как #ifdef, обрабатываются препроцессором до того, как компилятор когда-либо увидит ваш код, поэтому блок кода после директивы #ifdef может даже не быть скомпилирован .
Хранение директив, визуально отделенных от остальной части вашего кода, более важно, когда они перемежаются с кодом (а не с выделенным блоком директив, как в приведенном вами примере).
источник
Распространенное решение - прокомментировать директивы, чтобы вы легко знали, к чему они относятся:
источник
Практически во всех доступных в настоящее время компиляторах C / CPP это не ограничено. Пользователь сам решает, как вы хотите выровнять код. Так счастливого кодирования.
источник