Я хочу прокомментировать строку с помощью препроцессора:
#define open /##*
#define close */
main()
{
open commented line close
}
когда я делаю $gcc -E filename.c
Я ожидал
/* commented line */
но я добрался
/ * commented line */
так, чтобы компилятор показал ошибку
Почему это дает нежелательное пространство?
Препроцессор запускается и создает код в форме, понятной компилятору C. Он обрабатывает ваш код только один раз, поэтому даже если вы можете создать / *
с вашим #define
, компилятор увидит / *
и выдает ошибку, потому что это недопустимый код C (это инструкция предварительной обработки).
Это не кажется очень хорошим делом.
Ошибка связана с тем, что / *
не является допустимым токеном.
Как поясняется в документе CPP :
два токена, которые вместе не образуют действительный токен, не могут быть вставлены вместе. Например, вы не можете объединить
x
с+
в любом порядке.
Вы можете получить ошибку, вставив другую ерунду, например / ## +
или + ## -
.
Что касается пробела, то он вставлен намеренно, чтобы не создать комментарий и не испортить остальное. Из исходного кода GCC :
/* Avoid comment headers, since they are still processed in stage 3.
It is simpler to insert a space here, rather than modifying the
lexer to ignore comments in some circumstances. Simply returning
false doesn't work, since we want to clear the PASTE_LEFT flag. */
if ((*plhs)->type == CPP_DIV && rhs->type != CPP_EQ)
*end++ = ' ';
Потому что комментарии заменяются пробелами до (и только до) запуска препроцессора. Если вы вставите вместе символы /
и *
с помощью препроцессора, вы получите /*
, что является просто парой операторов. Edit: такое злоупотребление ##
технически создает /*
как один токен, который имеет неопределенное поведение. Вы можете склеивать > ## >
или < %:%: :
, хотя этого делать не следует.
См. §6.4.6 C99 о том, какие лексемы разрешено строить, и 6.10.3.3 о процессе катенации.
Если вы хотите прокомментировать какой-либо код с помощью препроцессора, используйте
#if 0
...
#endif
Из документации по препроцессору GNU C:
Однако два токена, которые вместе не образуют действительный токен, не могут быть вставлены вместе. Например, вы не можете объединить x с + в любом порядке. Если вы попытаетесь, препроцессор выдаст предупреждение и выдаст два токена. Не определено, помещает ли он пробелы между токенами. Часто встречается ненужное использование символа '##' в сложных макросах. Если вы получили это предупреждение, скорее всего, вы можете просто удалить '##'.
В этом случае '*' и '/' не образуют действительный токен C или C ++. Таким образом, они испускаются с пробелом между ними.
(Кроме того: вы, вероятно, получите ошибки компиляции C, даже если вам удастся вставить «комментарии» в вывод препроцессора C. Там не должно быть никаких комментариев.)
{{1 }}