Esto puede ser una cuestión de estilo, pero hay una pequeña división en nuestro equipo de desarrollo y me preguntaba si alguien más tenía alguna idea al respecto ...
Básicamente, tenemos algunas declaraciones de impresión de depuración que desactivamos durante el desarrollo normal. Personalmente prefiero hacer lo siguiente:
//---- SomeSourceFile.cpp ----
#define DEBUG_ENABLED (0)
...
SomeFunction()
{
int someVariable = 5;
#if(DEBUG_ENABLED)
printf("Debugging: someVariable == %d", someVariable);
#endif
}
Sin embargo, algunos miembros del equipo prefieren lo siguiente:
// #define DEBUG_ENABLED
...
SomeFunction()
{
int someVariable = 5;
#ifdef DEBUG_ENABLED
printf("Debugging: someVariable == %d", someVariable);
#endif
}
... ¿cuál de esos métodos te suena mejor y por qué? Mi sensación es que la primera es más segura porque siempre hay algo definido y no hay peligro de que pueda destruir otras definiciones en otros lugares.
c++
c
if-statement
coding-style
c-preprocessor
Jon Cage
fuente
fuente
#if
, también puede usarlo#elif
de manera coherente, a diferencia de con#ifdef
. Por lo tanto, en lugar de simplemente usar#define BLAH
, usar#define BLAH 1
con#if BLAH
, etc ...Respuestas:
Mi reacción inicial fue
#ifdef
, por supuesto , pero creo que en#if
realidad tiene algunas ventajas significativas para esto: he aquí por qué:Primero, puede usarlo
DEBUG_ENABLED
en preprocesadores y pruebas compiladas. Ejemplo: a menudo, quiero tiempos de espera más largos cuando la depuración está habilitada, por lo que al usar#if
, puedo escribir esto... en vez de ...
En segundo lugar, está en una mejor posición si desea migrar de una
#define
constante global a una.#define
La mayoría de los programadores de C ++ suelen desaprobar los s.Y, en tercer lugar, dice que hay una división en su equipo. Supongo que esto significa que diferentes miembros ya han adoptado diferentes enfoques y es necesario estandarizar. La regla que
#if
es la opción preferida significa que el código que se usa#ifdef
se compilará y se ejecutará incluso cuandoDEBUG_ENABLED
sea falso. Y es mucho más fácil rastrear y eliminar la salida de depuración que se produce cuando no debería ser que viceversa.Ah, y un pequeño punto de legibilidad. Debería poder usar verdadero / falso en lugar de 0/1 en su
#define
, y debido a que el valor es un solo token léxico, es la única vez que no necesita paréntesis alrededor.en vez de
fuente
#ifdef
es que funciona con cosas que no están definidas; si no están definidos intencionalmente o debido a un error tipográfico o lo que sea.#if DEBUG_ENBALED
no es un error detectado por el preprocesador. SiDEBUG_ENBALED
no está definido, se expande al token0
en las#if
directivas.Ambos son horribles. En su lugar, haz esto:
Luego, cuando necesite código de depuración, introdúzcalo
D();
. Y su programa no está contaminado con horribles laberintos de#ifdef
.fuente
#ifdef
solo verifica si un token está definido, dadoluego
fuente
Hemos tenido el mismo problema en varios archivos y siempre existe el problema de que las personas se olvidan de incluir un archivo de "indicador de características" (con una base de código de> 41.000 archivos es fácil de hacer).
Si tuvieras feature.h:
Pero luego olvidó incluir el archivo de encabezado en file.cpp:
Entonces tiene un problema, el compilador interpreta que COOL_FEATURE no está definido como "falso" en este caso y no incluye el código. Sí, gcc admite un indicador que causa un error para macros indefinidas ... pero la mayoría del código de terceros define o no define características, por lo que esto no sería tan portátil.
Hemos adoptado una forma portátil de corregir este caso, así como probar el estado de una característica: macros de función.
si cambió el feature.h anterior a:
Pero luego nuevamente olvidó incluir el archivo de encabezado en file.cpp:
El preprocesador se habría equivocado debido al uso de una macro de función no definida.
fuente
A los efectos de realizar la compilación condicional, #if y #ifdef son casi lo mismo, pero no del todo. Si su compilación condicional depende de dos símbolos, #ifdef no funcionará tan bien. Por ejemplo, suponga que tiene dos símbolos de compilación condicional, PRO_VERSION y TRIAL_VERSION, es posible que tenga algo como esto:
Usar #ifdef lo anterior se vuelve mucho más complicado, especialmente hacer que la parte #else funcione.
Trabajo en código que usa compilación condicional ampliamente y tenemos una mezcla de #if y #ifdef. Tendemos a usar # ifdef / # ifndef para el caso simple y #if siempre que se evalúen dos o más símbolos.
fuente
#if defined
qué esdefined
una palabra clave o?Creo que es completamente una cuestión de estilo. Ninguno tiene realmente una ventaja obvia sobre el otro.
La consistencia es más importante que cualquier elección en particular, por lo que le recomiendo que se reúnan con su equipo y elijan un estilo y lo mantengan.
fuente
Yo mismo prefiero:
Dado que facilita la creación de código que busca la condición opuesta, es mucho más fácil de detectar:
vs.
fuente
#if ! defined
para que sea!
más prominente y difícil de pasar por alto.Es cuestión de estilo. Pero recomiendo una forma más concisa de hacer esto:
Haz esto una vez, luego usa siempre debug_print () para imprimir o no hacer nada. (Sí, esto se compilará en ambos casos). De esta manera, su código no se alterará con las directivas del preprocesador.
Si recibe la advertencia "la expresión no tiene efecto" y desea deshacerse de ella, aquí tiene una alternativa:
fuente
#if
le da la opción de configurarlo en 0 para desactivar la funcionalidad, mientras sigue detectando que el interruptor está allí.Personalmente, siempre
#define DEBUG 1
puedo detectarlo con un #if o #ifdeffuente
#define DEBUG 1
. Not#define DEBUG=1
#if y #define MY_MACRO (0)
El uso de #if significa que creó una macro "definir", es decir, algo que se buscará en el código para ser reemplazado por "(0)". Este es el "infierno macro" que odio ver en C ++, porque contamina el código con posibles modificaciones de código.
Por ejemplo:
da el siguiente error en g ++:
Solo un error.
Lo que significa que su macro interactuó exitosamente con su código C ++: la llamada a la función fue exitosa. En este simple caso, es divertido. Pero mi propia experiencia con macros jugando silenciosamente con mi código no está llena de alegría y plenitud, así que ...
#ifdef y #define MY_MACRO
Usar #ifdef significa que "define" algo. No es que le des un valor. Todavía es contaminante, pero al menos, será "reemplazado por nada", y el código C ++ no lo verá como una declaración de código lagítima. El mismo código anterior, con una simple definición, es:
Da las siguientes advertencias:
Entonces...
Conclusión
Prefiero vivir sin macros en mi código, pero por múltiples razones (definir protecciones de encabezado o depurar macros), no puedo.
Pero al menos, me gusta hacerlos lo menos interactivos posible con mi código C ++ legítimo. Lo que significa usar #define sin valor, usar #ifdef y #ifndef (o incluso #if definido como lo sugiere Jim Buck), y sobre todo, darles nombres tan largos y tan extraños que nadie en su sano juicio usará "por casualidad", y que de ninguna manera afectará al código C ++ legítimo.
Post Scriptum
Ahora, mientras vuelvo a leer mi publicación, me pregunto si no debería intentar encontrar algún valor que nunca sea C ++ correcto para agregar a mi definición. Algo como
que podría usarse con #ifdef y #ifndef, pero no permitir que el código se compile si se usa dentro de una función ... Intenté esto con éxito en g ++, y dio el error:
Interesante. :-)
fuente
Eso no es una cuestión de estilo en absoluto. Además, la pregunta es, lamentablemente, incorrecta. No puede comparar estas directivas de preprocesador en el sentido de mejor o más seguro.
significa "si la macro está definida" o "si la macro existe". El valor de la macro no importa aquí. Puede ser lo que sea.
si siempre se compara con un valor. En el ejemplo anterior, es la comparación implícita estándar:
ejemplo para el uso de #if
ahora puede poner la definición de CFLAG_EDITION en su código
o puede establecer la macro como bandera del compilador. Vea también aquí .
fuente
El primero me parece más claro. Parece más natural convertirlo en una bandera en comparación con definido / no definido.
fuente
Ambos son exactamente equivalentes. En el uso idiomático, #ifdef se usa solo para verificar la definición (y lo que usaría en su ejemplo), mientras que #if se usa en expresiones más complejas, como #if definido (A) &&! Definido (B).
fuente
Un poco de OT, pero activar / desactivar el registro con el preprocesador es definitivamente subóptimo en C ++. Hay buenas herramientas de registro como log4cxx de Apache que son de código abierto y no restringen la forma en que distribuye su aplicación. También le permiten cambiar los niveles de registro sin recompilación, tienen una sobrecarga muy baja si apaga el registro y le dan la oportunidad de desactivarlo por completo en producción.
fuente
Solía usar
#ifdef
, pero cuando cambié a Doxygen para la documentación, descubrí que las macros comentadas no se pueden documentar (o, al menos, Doxygen produce una advertencia). Esto significa que no puedo documentar las macros de cambio de función que no están habilitadas actualmente.Aunque es posible definir las macros solo para Doxygen, esto significa que las macros en las partes no activas del código también se documentarán. Personalmente, quiero mostrar los cambios de función y, de lo contrario, solo documentar lo que está seleccionado actualmente. Además, hace que el código sea bastante complicado si hay muchas macros que deben definirse solo cuando Doxygen procesa el archivo.
Por tanto, en este caso, es mejor definir siempre las macros y utilizar
#if
.fuente
Siempre he usado #ifdef y banderas del compilador para definirlo ...
fuente
Alternativamente, puede declarar una constante global y usar C ++ if, en lugar del preprocesador #if. El compilador debería optimizar las ramas no utilizadas para usted, y su código será más limpio.
Esto es lo que dice C ++ Gotchas de Stephen C. Dewhurst sobre el uso de # if.
fuente
Hay una diferencia en el caso de una forma diferente de especificar una definición condicional para el controlador:
salida:
Esto significa que
-DA
es sinónimo de-DA=1
y si se omite el valor, puede generar problemas en caso de#if A
uso.fuente
Me gusta
#define DEBUG_ENABLED (0)
cuando es posible que desee varios niveles de depuración. Por ejemplo:Hace que sea más fácil depurar fugas de memoria, sin tener todas esas líneas de registro en su forma de depurar otras cosas.
Además,
#ifndef
alrededor de la definición hace que sea más fácil elegir un nivel de depuración específico en la línea de comandos:Si no fuera por esto, le daría ventaja
#ifdef
porque el indicador del compilador / marca sería anulado por el del archivo. Por lo tanto, no tiene que preocuparse por volver a cambiar el encabezado antes de realizar la confirmación.fuente