Как описано в этой копии- n-вставленное описание этапов перевода в стандарте C99, удаление комментариев (они заменяются одним пробелом) происходит на этапе перевода 3, в то время как директивы предварительной обработки обрабатываются, а макросы расширяются на этапе 4.
В стандарте C90 (который у меня есть только в бумажном виде, поэтому без копирования и вставки) эти две фазы происходят в одном и том же порядке, хотя описание фаз трансляции немного отличается в некоторых деталях от стандарта C99 - факт что комментарии удаляются и заменяются одним символом пробела перед обработкой директив предварительной обработки, а расширенные макросы ничем не отличаются.
Опять же, в стандарте C ++ эти две фазы выполняются в одном и том же порядке.
Что касается того, как следует обрабатывать комментарии '//
', стандарт C99 говорит следующее (6.4.9 / 2):
За исключением символьной константы, строкового литерала или комментария, символы // вводят комментарий, который включает в себя все многобайтовые символы до следующего символа новой строки, но не включая его.
И стандарт C ++ говорит (2.7):
Символы // начинают комментарий, который заканчивается следующим символом новой строки.
Итак, ваш первый пример явно является ошибкой со стороны этого переводчика - символ «;
» после foo(a)
должен быть сохранен при раскрытии макроса foo()
- символы комментария не должны быть частью «содержимого» макроса the foo()
.
Но поскольку вы столкнулись с ошибкой переводчика, вы можете изменить определение макроса на:
#define foo(x) /* junk */
чтобы обойти ошибку.
Однако (и я здесь отклоняюсь от темы ...), поскольку сращивание строк (обратная косая черта непосредственно перед новой строкой) происходит до обработки комментариев, вы можете столкнуться с чем-то вроде этого неприятного кода:
#define evil( x) printf( "hello "); // hi there, \
printf( "%s\n", x); // you!
int main( int argc, char** argv)
{
evil( "bastard");
return 0;
}
Что может удивить того, кто это написал.
Или, что еще лучше, попробуйте следующее, написанное кем-то (конечно, не мной!), Кому нравятся комментарии в виде прямоугольников:
int main( int argc, char** argv)
{
//----------------/
printf( "hello "); // Hey, what the??/
printf( "%s\n", "you"); // heck?? /
//----------------/
return 0;
}
В зависимости от того, обрабатывает ли ваш компилятор по умолчанию триграфы или нет (компиляторы должны , но поскольку триграфы удивляют почти всех, кто сталкивается с ними, некоторые компиляторы решают отключить их по умолчанию), вы можете получить или не получить желаемое поведение - независимо от его поведения, конечно.
person
Michael Burr
schedule
02.10.2009
//
комментарии, а компилятор понимает? Помните, что изначально C должен был понимать только/* */
комментарии, а//
был расширением C ++. Я думаю, что C подобрал//
только с C99. (Правильно ли я ввел здесь свою историю?). Фактически, какой бы компилятор вы ни использовали, мне любопытно посмотреть, как он обрабатывает/*
- person Aaron McDaid   schedule 19.02.2014