Это относится к включению или отключению условной компиляции. В нем обсуждается как использование целочисленных выражений, так и макросов препроцессора.
Допустим, вы хотите, чтобы какой-то код был включен только во время отладки. Вы можете сделать что-то вроде этого:
#define DEBUGGING 1
#if DEBUGGING
printf( "I'm debugging\n" );
#endif
void function( void ) {
if ( DEBUGGING ) {
printf( "I'm debugging\n" );
}
}
Этот код будет работать, т. е. вы получите два печатных оператора вывода, которые говорят: «Я отлаживаю».
Причина в том, что в первом блоке (#if DEBUGGING
) макрос DEBUGGING
преобразуется в 1 (значение, которое он должен представлять), а затем оценивается как целочисленное выражение. Другими словами, препроцессор сводит код к следующему:
#if 1
printf( "I'm debugging\n" );
#endif
void function( void ) {
if ( 1 ) {
printf( "I'm debugging\n" );
}
}
Но теперь рассмотрим случай, когда макрос #DEBUGGING
вообще не определен.
В этом случае препроцессор сократит код до такого:
//#define DEBUGGING 1 <-- commented out
#if 0 // <--- DEBUGGING is not a macro-word here, so it is converted to 0
printf( "I'm debugging\n" );
#endif
void function( void ) {
if ( DEBUGGING ) { // <---- look what happened here! *Not* in "#if", so NOT preprocessed to zero!
printf( "I'm debugging\n" );
}
}
Из-за того, как определен язык C, тест #if
уменьшит любое слово, которое не распознается как макрос (например, int, sizeof, myVariableName, SOME_OTHER_UNDEFINED_THING), до 0, и ошибка не будет выдана. Первый оператор printf просто не будет скомпилирован.
Однако второй оператор, использующий то, что было макросом в предыдущей версии кода, НЕ получит замену, поскольку макрос DEBUGGING
больше не определен. В этом случае после запуска препроцессора компилятор будет жаловаться на имя, которое он не распознает, поскольку он буквально увидит слово DEBUGGING
и не будет знать, что с ним делать (это не имя переменной или ключевое слово и т. ).
Это первое, о чем говорит процитированный вами абзац.
Во-вторых, он упоминает, что операторы #if
уменьшат свои аргументы до результата одного целочисленного выражения. Это означает, что вы можете скомпилировать код, который выглядит так:
#define VERSION 2
#if VERSION > 1
printf( "this code only runs on v2+\n" );
#endif
Препроцессор сначала заменяет слово VERSION тем, что оно представляет:
#if 2 > 1
...
затем препроцессор оценивает строку как целочисленное выражение. Поскольку 2 больше 1 (истина), выражение/строка сводится к:
#if 1
printf( "this code only runs on v2+\n" );
#endif
Что касается sizeof
(и любого другого ключевого слова или слова, не являющегося макросом), в операторах #if
все имена, которые не распознает препроцессор, преобразуются в ноль. Это сделано для того, чтобы он мог обрабатывать условную компиляцию макросов, которых нет, как показано выше, когда я закомментировал DEBUGGING
.
Итак, этот код, который выглядит как то, что вы, возможно, захотите сделать:
#if sizeof(int) > 2
printf( "This machine has 4+ byte integers\n" );
#endif
Сократится до этого:
#if 0(0) > 2 // sizeof and int are non-macro-words so they get replaced with 0
Это недопустимое выражение, поэтому компилятор сообщит об ошибке. Таким образом, вы не можете использовать sizeof
(или любое другое ключевое слово или имя переменной) в макросе препроцессора.
Если вы думаете об этом, отделив препроцессор C от компилятора C, это имеет смысл. Препроцессор не знает об обычных ключевых словах C, это не его работа. Он просто анализирует интересующие его токены (#if
и т. д.), а затем передает обработанный C-файл компилятору.
person
par
schedule
28.09.2014
#if defined NAME
– gcc.gnu.org/onlinedocs/cpp/Defined.html - person Karoly Horvath   schedule 28.09.2014