¿Qué hace exactamente un bloque #if 0… #endif?


124

En C / C ++

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

#if 0

//Code goes here

#endif

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


17
Esta es una técnica que se utiliza para comentar grandes cantidades de código o para permitir probar la inclusión de bloques de código. Sin esta característica, uno tendría que prefijar cada línea con //o comenzar la sección con /*y terminar la sección con */. El problema con las últimas técnicas es que los comentarios no se anidan, por lo que el desarrollador debe verificar y manejar cualquiera */entre el inicio y el final.
Thomas Matthews

Respuestas:


141

No solo no se ejecuta, ni siquiera se compila.

#ifes 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 usa para eliminar temporalmente segmentos de código con la intención de volver a activarlos más tarde.


1
Esto es cierto para cualquier tipo de comentario. La diferencia importante es el anidamiento.
Samy Bencherif

73

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

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

Si quiero comentarlo, puedo intentar:

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

Bzzt. ¡Error de sintaxis! ¿Por qué? Debido a que los comentarios de bloque no se anidan, por lo que (como puede ver en el resaltado de sintaxis de SO) */después de la palabra "NULL" termina el comentario, lo que hace que la bazllamada no esté comentada y */después bazun error de sintaxis. Por otra parte:

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

Funciona para comentar todo. Y los #if 0s anidarán 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 resultar un poco confuso y convertirse en un dolor de cabeza de mantenimiento si no se comenta correctamente.


5
Solo tenga en cuenta que el código dentro de #if tiene que ser léxicamente correcto (a diferencia de los comentarios) y las directivas del preprocesador aún están en vigor (ídem).
jpalecek

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

1
@Dennis, recibo foo.c:3: unterminated string or character constantde gcc, ¿qué estás usando?
David X

18

Comenta permanentemente ese código para que el compilador nunca lo compile.

El codificador puede luego cambiar el #ifdef para que ese código se compile en el programa si así lo desea.

Es exactamente como si el código no existiera.


15

¿Qué hace exactamente un bloque #if 0… #endif?

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


12

Me gustaría agregar para el #elsecaso:

#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

7

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

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

Si desea comprender lo que sucedió 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.


No exactamente. El preprocesador analiza por línea en lugar de por token. Según su explicación, no sería posible decir, por ejemplo, #if WIN32 || __CYGWIN__pero funciona como se esperaba.
Ben Voigt

Estaba simplificando. Si hay un o, comprobará si alguno de los tokens es distinto de cero. Del mismo modo, si hay un y comprobará si ambos son distintos de cero.
Steve Rowe

3

Las líneas que comienzan con a #son directivas de preprocesador . #if 0 [...] #endiflos bloques no llegan al compilador y no generarán código de máquina.

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

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

La ejecución gcc -E ifdef.cxxle mostrará lo que se compila.

Puede optar por utilizar este mecanismo para evitar que se compile un bloque de código durante el ciclo de desarrollo, pero probablemente no desee registrarlo en su control de código fuente, ya que simplemente agrega cruft a su código y reduce la legibilidad. Si se trata de un código histórico que se ha comentado, entonces debería eliminarse: el control de código fuente contiene el historial, ¿verdad?

Además, la respuesta puede ser la misma para C y C ++, pero no existe un lenguaje llamado C / C ++ y no es un buen hábito referirse a dicho lenguaje.


4
¿Qué tiene de malo decir C / C ++ como abreviatura de "C o C ++"? ¿De verdad crees que alguien se confundirá al pensar que existe un lenguaje llamado "C / C ++"?
Christopher Barber

1
@Chris: La gente constantemente hace preguntas como "¿Cómo hago X en C / C ++?" Cuál es una pregunta sin sentido; está codificando en uno u otro, y si aún no lo ha elegido, debe ser explícito en ese hecho. Entonces, sí, la gente está confundida acerca de la existencia de un lenguaje llamado "C / C ++"
Dennis Zickefoose

1
¡Qué declaración más absurda! 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 esté haciendo una pregunta general no significa que no sepa qué idioma está utilizando. Si sospecha que ese es el caso, como en esta pregunta, ¿cómo ayuda especificar C o C ++? ¿Cree que sería útil que todas las preguntas que pudieran aplicarse a C o C ++ se hicieran dos veces?
Christopher Barber

@Christopher: Tienes razón, hay muchas preguntas en las que las respuestas son igualmente relevantes para C, C ++ y Objective-C (esta es una de ellas). Stack Overflow tiene un práctico sistema de etiquetado para indicar a qué idiomas pertenece una pregunta. Como menciona @Dennis, SO (y otros foros de programación [foros?]) Hay (demasiadas) personas que están confundidas en cuanto a la delineación entre C y otros lenguajes derivados de C que se refieren a estos lenguajes indistintamente como C / C ++, lo que lo hace más difícil de responder a la pregunta en el idioma apropiado.
Johnsyweb

2

No exactamente

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

Muestra "tc: 4: 19: advertencia: falta el carácter de terminación" con gcc 4.2.4


2
Esta advertencia la genera el preprocesador, no el compilador. El compilador solo ve: # 1 "tc" # 1 "<built-in>" # 1 "<command-line>" # 1 "tc" int main (void) {return 0; }
Johnsyweb

0

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

Además, sospecho que 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.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.