¿Por qué usar #if 0 para bloquear los comentarios?

11 minutos de lectura

avatar de usuario
jason r mick

Código de ingeniería inversa y estoy un poco horrorizado por el estilo, pero quería asegurarme de que no hay una buena razón para hacer estas cosas…

¿Soy solo yo o es un estilo de codificación horrible?

if ( pwbuf ) sprintf(username,"%s",pwbuf->pw_name);
else sprintf(username,"%d",user_id);

¿Y por qué envolver el código no destinado a la compilación en un

#if 0
....
#endif

en lugar de comentarios?


EDITAR: Entonces, como algunos explicaron a continuación, esto se debe a la posibilidad de desconcertar /* */ que no me di cuenta.

Pero sigo sin entender, ¿por qué no usar las herramientas de su entorno de programación o las macros de su editor de texto favorito para bloquear los comentarios usando “//”?

¿No sería esto MUCHO más sencillo y fácil de saber omitir visualmente?


¿Solo soy inexperto en C y me falta por qué estas cosas podrían ser una buena idea, ¿o no hay excusa, y estoy justificado para sentirme irritado por lo feo que es este código?

  • Lo he hecho antes, por alguna razón parece más claro. Nunca he visto directivas de preprocesador para comentar el código.

    – Nóvikov

    2 de septiembre de 2010 a las 19:42

  • @Novikov: He visto mucho ese uso de directivas de preprocesador: D

    – BoltClock

    2 de septiembre de 2010 a las 19:49

  • Es un poco feo, pero no completo. feo. Tiene la posibilidad de verse mucho mejor solo con gafas de cerveza ligeras a moderadas.

    – FrustradoConFormsDesigner

    02/09/2010 a las 19:50


  • He hecho eso de la directiva del preprocesador. La ventaja es que mantiene el formato de su código y la codificación de colores. También es más fácil activar el bloque de código que los comentarios.

    – nmichaels

    02/09/2010 a las 20:34

  • También minimiza las diferencias y hace que los parches sean infinitamente más fáciles de leer.

    – Dan Bechard

    7 junio 2017 a las 21:04

avatar de usuario
jkerian

#if 0 se usa con bastante frecuencia cuando el bloque eliminado contiene comentarios de bloque

No diré que es una buena práctica, pero lo veo bastante a menudo.

La declaración de control de flujo de una sola línea es bastante fácil de entender, aunque personalmente la evito (y la mayoría de las pautas de codificación con las que he trabajado lo prohíben)

Por cierto, probablemente editaría el título para que sea algo útil “¿Por qué usar #if 0 en lugar de bloquear comentarios?”

Si tienes lo siguiente

#if 0
        silly();
        if(foo)
           bar();
        /* baz is a flumuxiation */
        baz = fib+3;
#endif

Si reemplaza ingenuamente el #if 0/#endif con /* */eso hará que el comentario finalice justo después de flumuxiation, causando un error de sintaxis cuando presione el botón */ en el lugar de la #endif arriba..

EDIT: Una nota final, a menudo el #if 0 la sintaxis solo se usa durante el desarrollo, particularmente si tiene que soportar múltiples versiones o dependencias o plataformas de hardware. No es raro que el código se modifique para

#ifdef _COMPILED_WITHOUT_FEATURE_BAZ_
    much_code();
#endif

Con un encabezado centralizado que define (o no) cientos de esas constantes #define. No es la cosa más bonita del mundo, pero cada vez que trabajé en un proyecto de tamaño decente, usamos alguna combinación de interruptores de tiempo de ejecución, constantes de tiempo de compilación (esto), decisiones de compilación de tiempo de compilación (simplemente use diferentes . cpp’s dependiendo de la versión), y la solución de plantilla ocasional. Todo depende de los detalles.

Si bien eres el desarrollador, solo haces que todo funcione en primer lugar, sin embargo… #if 0 es bastante común si no está seguro de si el código anterior aún tiene valor.

  • Un editor decente también atenuará el código #if 0’d, por lo que no es un gran problema. Editando con un ejemplo.

    – jkerian

    2 de septiembre de 2010 a las 19:46

  • @Jason No puedes usar /**/ para comentar otros /**/, no anidan.

    – ioan

    2 de septiembre de 2010 a las 19:49

  • Como señaló jkerian, si el código que está comentando ya tiene una comilla en bloque, entonces agregar otro conjunto de comillas en bloque no funcionará. Usar #if 0 es una forma mucho mejor de hacerlo.

    – Torlack

    2 de septiembre de 2010 a las 19:51

  • @Jasaon: porque /* */ comentarios para no anidar. Entonces, si los usa para ocultar el código que contiene un comentario, el comentario (externo) terminará en el primer */.

    – James Curran

    2 de septiembre de 2010 a las 19:51

  • Si bien esto es factible en la mayoría de los editores, le sugiero que reflexione sobre el hecho de que “/* */” son “bloquear comentarios” y // indica un “comentario de línea”. #if 0 El mecanismo funciona de manera muy similar a los comentarios de bloque, y tiene sentido que sea preferible.

    – jkerian

    2 de septiembre de 2010 a las 20:03

avatar de usuario
jeff dege

Los comentarios son comentarios. Describen el código.

El código que se excluye de la compilación es código, no comentarios. A menudo incluirá comentarios que describen el código que no se está compilando, por el momento.

Son dos conceptos distintos, y forzar la misma sintaxis me parece un error.


Estoy editando esto porque estoy en medio de una refactorización considerable y estoy haciendo un uso intensivo de este patrón.

Como parte de esta refactorización, estoy eliminando algunos tipos ampliamente utilizados y reemplazándolos por otros. El resultado, por supuesto, es que nada se construirá.

Y realmente odio pasar días arreglando un problema tras otro con la esperanza de que cuando termine todo se construirá y todas las pruebas se ejecutarán.

Así que mi primer paso es #ifdef-out todo el código que no se compilará, y luego [Ignore] todas las pruebas unitarias que lo llaman. Una vez hecho esto, todo se construye y todas las pruebas no ignoradas pasan.

El resultado es una gran cantidad de funciones que se ven así:

public void MyFunction()
{
#if true
    throw new NotImplementedException("JT-123");
#else
    // all the existing code that won't compile
#endif
}

Luego designoro las pruebas unitarias, una a la vez, y luego corrijo las funciones, una a la vez.

Me tomará un par de días evaluarlo todo, y todos estos #si desaparecerán antes de crear la solicitud de incorporación de cambios para fusionar esto, pero lo encuentro útil durante el proceso.

  • +1 Esta es una buena racionalización. Haces un buen argumento a favor siempre usando el preprocesador para excluir código. Seguro que es un poco feo, pero código muerto debería ser feo, ¿verdad?

    – P papá

    3 de septiembre de 2010 a las 15:31

  • Uno podría señalar que comentar el código que no se usa (sin importar si se hace con comentarios o con directivas de preprocesador) es un mal uso porque esa es la tarea de un SCM. En caso de que desee conservar una versión anterior de un fragmento de código (por ejemplo, para evitar cometer un error dos veces), este código definitivamente se convierte en un comentario estático (código mezclado con explicaciones útiles) que ya no tiene nada que ver con el código de tu programa Dado que siempre sería incorrecto excluir el código de la compilación.

    – Kalle Richter

    29 de agosto de 2015 a las 17:11

  • No diré siempre, pero en general estoy de acuerdo contigo. Creo que la práctica adecuada sería limpiar este tipo de desorden antes del check-in.

    –Jeff Dege

    30 de agosto de 2015 a las 12:39

Además del problema con los comentarios de estilo C que no se anidan, deshabilitar bloques de código con #if 0 tiene la ventaja de poder contraerse si está utilizando un editor que admita el plegado de código. También es muy fácil de hacer en cualquier editor, mientras que deshabilitar grandes bloques de código con comentarios de estilo C++ puede ser difícil de manejar sin el soporte del editor/macros.

Además, muchos #if 0 los bloques tienen un else bloquear también. Esto brinda una manera fácil de cambiar entre dos implementaciones/algoritmos, y podría decirse que es menos propenso a errores que comentar en masa una sección y descomentar en masa otra. Sin embargo, sería mejor usar algo más legible como #if DEBUG en ese evento.

En cuanto a bloquear los comentarios usando // en lo que respecta, una de las razones que se me ocurre es que, si verifica ese código en su sistema de control de código fuente, el registro de culpas lo mostrará como el último editor de esas líneas de código. Si bien es probable que desee que se le atribuyan los comentarios, al mismo tiempo también se le atribuye el código en sí. Claro, puede regresar y ver las revisiones anteriores si necesita verificar el registro de culpas del autor “real” del código, pero ahorraría tiempo si se conservara esa información en la revisión actual.

Esa es una C bastante idiomática. No veo qué tiene de malo. No es una hermosa pieza de código, pero es fácil de leer y es claro lo que está pasando y por qué, incluso sin contexto.

Los nombres de las variables podrían ser mejores y probablemente sería más seguro usarlos snprintf o quizás strncpy.

Si crees que podría ser mejor, ¿cómo te gustaría que fuera?

Podría hacer un pequeño cambio:

char username[32];
strncpy(username, 30, (pwbuf ? pwbuf->pw_name : user_id));
username[31] = '\0';

  • Supongo que preferiría ver la lógica else puesta en la siguiente línea. Quiero decir que yo comprender lo que está haciendo, pero cuando veo por primera vez “else” y luego lo que parece un condicional, mi cerebro se derrite. Simplemente me molesta por alguna razón. Nuevamente, tal vez no sea lógico, por eso hice la pregunta… ¿Tal vez tengo que volver a entrenar mi cerebro para pensar que es una buena idea?

    – Jason R.Mick

    2 de septiembre de 2010 a las 19:49

  • En este caso el “cambio ligero” no funcionará en absoluto, porque user_id es un int y necesita ser renderizado usando %d.

    – Steve cumbre

    9 de julio de 2021 a las 11:14

avatar de usuario
Oliver Charlesworth

Obviamente, cada uno tiene sus propias opiniones sobre este tipo de cosas. Así que aquí está el mío:

me gustaría nunca escribir código como el anterior, y pensaría menos en cualquiera que lo hiciera. No puedo contar la cantidad de veces que las personas piensan que está bien escaparse sin aparatos ortopédicos y luego les muerde.

Poner la declaración de control en la misma línea que el bloque de código es aún peor; la falta de sangría hace que sea más difícil ver el control de flujo durante la lectura. Una vez que haya estado codificando durante algunos años, se acostumbrará a poder leer e interpretar el código de forma rápida y precisa, siempre que pueda confiar en ciertas señales visuales. Eludir estas señales para “casos especiales” significa que el lector tiene que detenerse y hacer una doble toma, sin una buena razón.

#if (0)por otro lado, está bien durante el desarrollo, pero debe eliminarse una vez que el código sea “estable” (o al menos reemplazar 0 con algún nombre de símbolo de preprocesador significativo).

  • Supongo que preferiría ver la lógica else puesta en la siguiente línea. Quiero decir que yo comprender lo que está haciendo, pero cuando veo por primera vez “else” y luego lo que parece un condicional, mi cerebro se derrite. Simplemente me molesta por alguna razón. Nuevamente, tal vez no sea lógico, por eso hice la pregunta… ¿Tal vez tengo que volver a entrenar mi cerebro para pensar que es una buena idea?

    – Jason R.Mick

    2 de septiembre de 2010 a las 19:49

  • En este caso el “cambio ligero” no funcionará en absoluto, porque user_id es un int y necesita ser renderizado usando %d.

    – Steve cumbre

    9 de julio de 2021 a las 11:14

avatar de usuario
smdrager

¡Ahí está! No reacciones de forma exagerada…

Lo llamaría más descuidado por más el espacio inconsistente que cualquier otra cosa. He tenido tiempo en el que me pareció mejor poner declaraciones cortas en la misma línea que su IF, aunque esas declaraciones lo están estirando.

El estilo en línea es mejor para la brevedad vertical… podría dividirse fácilmente en 4 líneas más

if (pwbuf) 
  sprintf(username,"%s",pwbuf->pw_name); 
else 
  sprintf(username,"%d",user_id); 

Personalmente, odio el siguiente estilo, ya que es muy extenso, lo que dificulta hojear un archivo.

if (pwbuf) 
{
  sprintf(username,"%s",pwbuf->pw_name); 
}
else
{ 
  sprintf(username,"%d",user_id); 
}

  • La razón por la que se prefieren los corchetes adicionales es para evitar que alguien agregue una línea adicional más tarde y piense que será parte de la cláusula original.

    – Kenoyer130

    02/09/2010 a las 20:00


  • los corchetes son mucho más a prueba de futuro.

    – Pablo Nathan

    2 de septiembre de 2010 a las 20:01

  • Si goto fail nos enseñó algo… stackoverflow.com/questions/21999473/… Pondría las llaves en la misma línea que if y else (excepto el último) para reducir el número de líneas.

    – Interartículo

    12/01/2015 a las 21:51


  • Qué pasa #if 0/#if 1 ¿declaraciones?

    – Kalle Richter

    29 de agosto de 2015 a las 17:14

¿Ha sido útil esta solución?