2010-05-17 18 views
89

En C/C++¿Qué hace exactamente un bloque #if 0 ..... #endif?

¿Qué ocurre con código colocado entre un bloque de #if 0/#endif?

#if 0 

//Code goes here 

#endif 

¿El código simplemente se omite y, por lo tanto, no se ejecuta?

+11

Esta es una técnica utilizada para comentar de salida de grandes cantidades de código o para permitir las pruebas de inclusión de bloques de código. Sin esta característica, uno tendría que prefijar cada línea con '//' o iniciar la sección con '/ *' y finalizar la sección con '* /'. El problema con las últimas técnicas es que los comentarios no anidan, por lo que el desarrollador debe verificar y manejar cualquier '* /' entre el inicio y el final. –

+1

posible duplicado de [¿Por qué alguien usaría una directiva de preprocesador if 1 c] (http://stackoverflow.com/questions/2266060/why-would-somebody-use-an-if-1-c-preprocessor-directive) –

Respuesta

109

No solo no se ejecuta, ni siquiera se compila.

#if es un comando de preprocesador, que se evalúa antes del paso de compilación real. El código dentro de ese bloque no aparece en el binario compilado.

A menudo se utiliza para eliminar temporalmente segmentos de código con la intención de volverlos a encender más tarde.

+48

... vuelve más tarde, pero a menudo se olvida y hace que el código sea horrible de leer. – pmr

+2

^^ Literalmente exactamente lo que estoy pasando en este momento ... –

17

Comentarios permanentes de ese código por lo que el compilador nunca compilará.

El codificador puede posteriormente cambiar el #ifdef para compilar ese código en el programa si así lo desea.

Es exactamente como el código no existe.

61

Es idéntico a comentar el bloque, excepto con una diferencia importante: anidar no es un problema. Considere este código:

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

Si quiero comentar que, yo podría intentar:

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

Bzzt. ¡Error de sintaxis! ¿Por qué? Como los comentarios de bloque no anidan, y así (como se puede ver en el resaltado de sintaxis de SO), el */ después de la palabra "NULL" termina el comentario, haciendo que la llamada baz no esté comentada y */ después de baz un error de sintaxis. Por otro lado:

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

Funciona para comentar todo el asunto. Y el #if 0 s nido voluntad entre sí, así:

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

Aunque, por supuesto, esto puede ser un poco confuso y convertirse en un dolor de cabeza de mantenimiento si no ha comentado correctamente.

+4

Solo tenga en cuenta que el código dentro de #if debe ser léxicamente correcto (en oposición a los comentarios) y las directivas de preprocesador siguen vigentes (ídem). – jpalecek

+0

@David: no es léxicamente correcto, pero aún se compilará. Entonces el código no tiene que ser léxicamente correcto. –

+1

@Dennis, obtengo 'foo.c: 3: cadena sin terminar o constante de caracteres' de gcc, ¿qué estás usando? –

6

Cuando el preprocesador ve # si comprueba si el siguiente token tiene un valor distinto de cero. Si lo hace, mantiene el código para el compilador. Si no lo hace, se deshace de ese código para que el compilador nunca lo vea.

Si alguien dice #if 0 están efectivamente comentando el código para que nunca se compile. Puedes pensar que esto es lo mismo que si hubieran puesto/* ... */a su alrededor. No es exactamente lo mismo, pero tiene el mismo efecto.

Si quiere entender lo que pasó en detalle, a menudo puede mirar. Muchos compiladores le permitirán ver los archivos después de que se haya ejecutado el preprocesador. Por ejemplo, en Visual C++, el comando switch/P ejecutará el preprocesador y colocará los resultados en un archivo .i.

+0

No del todo. El preprocesador analiza por línea en lugar de por token. De acuerdo con su explicación, no sería posible decir, p. '#if WIN32 || __CYGWIN__' pero esto funciona como se esperaba. –

+0

Estaba simplificando. Si hay una o, comprobará si cualquiera de los tokens no es cero. Del mismo modo, si hay un y comprobará si ambos son distintos de cero. –

3

Las líneas que comienzan con # son preprocessor directives. Los bloques #if 0 [...] #endif no llegan al compilador y no generarán código de máquina.

Puede demostrar lo que sucede con el preprocesador con un archivo de origen ifdef.cxx:

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

Correr gcc -E ifdef.cxx le mostrará lo que se compila.

Puede optar por utilizar este mecanismo para evitar la compilación de un bloque de código durante el ciclo de desarrollo, pero es probable que no desee controlarlo con el control de origen ya que simplemente agrega cruzado a su código y reduce la legibilidad. Si se trata de un fragmento de código histórico que se ha comentado, debe eliminarse: el control de origen contiene el historial, ¿no?

Además, la respuesta puede ser el mismo para ambos C y C++ pero no hay un lenguaje llamado C/C++ y no es un buen hábito para referirse a un lenguaje tal.

+4

¿Qué hay de malo en decir C/C++ como abreviación para "C o C++"? ¿De verdad crees que alguien va a confundirse al pensar que hay un lenguaje llamado "C/C++"? –

+1

@Chris: las personas constantemente hacen preguntas como "¿Cómo hago X en C/C++?" Que es una pregunta sin sentido; estás codificando en uno u otro, y si aún no has elegido, debes ser explícito en ese hecho. Entonces, sí, la gente está confundida acerca de que haya un lenguaje llamado "C/C++" –

+1

¡Qué declaración sin sentido! Hay miles de preguntas cuyas respuestas son relevantes tanto para C como para C++. Recuerde que este es un sitio para hacer preguntas. El hecho de que haga una pregunta general no significa que no sepa qué idioma está usando. Si sospecha que es así, como en esta pregunta, ¿cómo ayuda especificar C o C++? ¿Crees que sería útil que cada pregunta que podría aplicarse a C o C++ se le pregunte dos veces? –

1

No del todo

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

Se muestra "tc: 4: 19: Aviso: falta de terminación" carácter" con gcc 4.2.4

+2

Esta advertencia la genera el preprocesador, no el compilador. El compilador sólo llega a ver: # 1 "tc" # 1 "" # 1 "" # 1 "tc" int main (void) { retorno 0 ; } – Johnsyweb

13

Qué hace exactamente un #if 0 # ... endif block do?

Le dice que el autor obviamente nunca ha oído hablar de un sistema de control de versiones. Lo cual, a su vez, te dice que corras lo más lejos posible & hellip;

1

Es una forma barata de comentar, pero sospecho que podría tener un potencial de depuración. Por ejemplo, supongamos que tiene una compilación que arroje valores a un archivo. Es posible que no desee eso en una versión final para que pueda usar el #if 0 ... #endif.

Además, sospecho una mejor manera de hacerlo con fines de depuración sería hacer:

#ifdef DEBUG 
// output to file 
#endif 

Puede hacer algo así y podría tener más sentido y todo lo que tiene que hacer es definir DEBUG para ver los resultados

7

me gustaría añadir en el caso de #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 
Cuestiones relacionadas