2010-05-17 4 views
89

В C/C++Что именно делает блок #if 0 ..... #endif?

Что происходит код, который размещен между #if 0/#endif блок?

#if 0 

//Code goes here 

#endif 

Выполняется ли код просто и поэтому не выполняется?

+11

Это метод, используемый для закомментировать большое количество кода или разрешить тестирование включения блоков кода. Без этой функции нужно было бы либо префикс каждой строки '//', либо начать раздел с '/ *' и завершить раздел с помощью '* /'. Проблема с последними методами заключается в том, что комментарий не вложен, поэтому разработчик должен проверять и обрабатывать любые '* /' между началом и концом. –

+1

Возможный дубликат [Почему кто-то использует директиву препроцессора if 1] (http://stackoverflow.com/questions/2266060/why-would-somebody-use-an-if-1-c-preprocessor-directive) –

ответ

109

Он не только не выполнен, он даже не скомпилирован.

#if - это команда препроцессора, которая оценивается до фактического этапа компиляции. Код внутри этого блока не отображается в скомпилированном двоичном файле.

Он часто используется для временного удаления сегментов кода с целью их последующего включения.

+48

... позже, но часто забывается и делает код ужасным для чтения. – pmr

+2

^^ Буквально точно, что я сейчас переживаю ... –

17

Он постоянно комментирует этот код, поэтому компилятор его не скомпилирует.

Кодер может позже изменить #ifdef, чтобы этот код был скомпилирован в программе, если захочет.

Это точно так же, как кода не существует.

61

Это идентично комментированию блока, за исключением одного важного отличия: вложение не является проблемой. Рассмотрим этот код:

foo(); 
bar(x, y); /* x must not be NULL */ 
baz(); 

Если я хочу комментировать это, я мог бы попробовать:

/* 
foo(); 
bar(x, y); /* x must not be NULL */ 
baz(); 
*/ 

Bzzt. Ошибка синтаксиса! Зачем? Поскольку комментарии блока не гнездятся, и поэтому (как вы можете видеть из подсветки синтаксиса SO), */ после слова «NULL» завершает комментарий, делая вызов baz не закомментированным, а */ после baz - синтаксической ошибкой. С другой стороны:

#if 0 
foo(); 
bar(x, y); /* x must not be NULL */ 
baz(); 
#endif 

Работы, чтобы прокомментировать все это. И в #if 0 воли гнездо друг с другом, например, так:

#if 0 
pre_foo(); 
#if 0 
foo(); 
bar(x, y); /* x must not be NULL */ 
baz(); 
#endif 
quux(); 
#endif 

Хотя, конечно, это может получить немного запутанными и стать поддержанием головной болью, если не комментировало должным образом.

+4

Просто обратите внимание, что код внутри #if должен лексически корректно (в отличие от комментариев), а директивы препроцессора все еще действуют (то же самое). – jpalecek

+0

@David: Его не лексически правильно, но он все равно будет компилироваться. Таким образом, код не должен лексически корректным. –

+1

@Dennis, я получаю 'foo.c: 3: unterminated string или character constant' из gcc, что вы используете? –

6

Когда препроцессор видит #if, он проверяет, имеет ли следующий токен ненулевое значение. Если это так, он сохраняет код для компилятора. Если это не так, он избавляется от этого кода, поэтому компилятор его никогда не видит.

Если кто-то говорит #if 0, они эффективно комментируют код, поэтому он никогда не будет скомпилирован. Вы можете думать об этом так же, как если бы они положили/* ... */вокруг него. Это не совсем то же самое, но он имеет тот же эффект.

Если вы хотите понять, что произошло подробно, вы можете часто смотреть. Многие компиляторы позволят вам видеть файлы после запуска препроцессора. Например, на Visual C++ команда switch/P выполнит препроцессор и поместит результаты в файл .i.

+0

Не совсем. Препроцессор анализирует по строкам, а не по токенам. Согласно вашему объяснению, было бы невозможно сказать, например. '#if WIN32 || __CYGWIN__', но это работает должным образом. –

+0

Я упрощал. Если есть или, он будет проверять, отличен ли токен от нуля. Аналогично, если есть, и он будет проверять, являются ли оба ненулевыми. –

3

Линии, начинающиеся с #, являются preprocessor directives. Блоки #if 0 [...] #endif не попадают в компилятор и не генерируют машинный код.

Вы можете продемонстрировать, что происходит с препроцессором с исходным файлом ifdef.cxx:

#if 0 
This code will not be compiled 
#else 
int i = 0; 
#endif 

Запуск gcc -E ifdef.cxx покажет вам, что компилируется.

Вы можете использовать этот механизм для предотвращения компиляции блока кода во время цикла разработки, но вам, вероятно, не захочется проверять его на исходный элемент управления, поскольку он просто добавляет к вашему коде код и уменьшает читаемость. Если это исторический фрагмент кода, который был прокомментирован, его следует удалить: исходный элемент управления содержит историю, не так ли?

Кроме того, ответ может быть таким же, как для C и C++, но нет языка называется C/C++, и это не очень хорошая привычка обращаться к такому языку.

+4

Что не так с высказыванием C/C++ как сокращение для «C или C++»? Вы честно думаете, что кто-то будет путать, подумав, что существует язык под названием «C/C++»? –

+1

@ Крис: Люди постоянно задают такие вопросы, как «Как мне сделать X в C/C++?» Это вопрос бессмысленный; вы кодируете одно или другое, и если вы еще не выбрали, вы должны быть явным в этом факте. Итак, да, люди смущены тем, что существует язык под названием «C/C++» –

+1

Что за бессмысленное утверждение! Есть тысячи вопросов, ответы на которые имеют отношение как к C, так и к C++. Помните, что это сайт для вопросов. Просто потому, что вы задаете общий вопрос, не означает, что вы не знаете, какой язык вы используете. Если вы подозреваете, что это так, как в этом вопросе, как это помогает указать C или C++? Считаете ли вы, что было бы полезно, если бы каждый вопрос, который мог бы применяться к C или C++, задавался дважды? –

1

Не совсем

int main(void) 
{ 
    #if 0 
    the apostrophe ' causes a warning 
    #endif 
    return 0; 
} 

Он показывает "дц: 4: 19: предупреждение: Отсутствует завершение" символ" с GCC 4.2.4

+2

Это предупреждение генерируется препроцессором, а не компилятором. Компилятор только получает, чтобы увидеть: # 1 "Т" # 1 "" # 1 "<командной строки>" # 1 "Т" INT основной (Недействительными) { возвращение 0 ; } – Johnsyweb

13

Что именно делает #if 0 ... # endif блок делаю?

Сообщается, что автор, очевидно, никогда не слышал о системе контроля версий. Который, в свою очередь, подскажет вам бежать как можно дальше & hellip;

1

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

Кроме того, я подозреваю, что лучший способ сделать это для отладки цели будет делать:

#ifdef DEBUG 
// output to file 
#endif 

Вы можете сделать что-то подобное, и это могло бы иметь больше смысла и все, что вам нужно сделать, это определить DEBUG чтобы увидеть результаты.

7

Я хотел бы добавить на для #else случая:

#if 0 
    /* Code here will NOT be complied. */ 
#else 
    /* Code will be compiled. */ 
#endif 


#if 1 
    /* Code will be complied. */ 
#else 
    /* Code will NOT be compiled. */ 
#endif 
Смежные вопросы