En toda nuestra base de código C, veo cada macro definida de la siguiente manera:
#ifndef BEEPTRIM_PITCH_RATE_DEGPS
#define BEEPTRIM_PITCH_RATE_DEGPS 0.2f
#endif
#ifndef BEEPTRIM_ROLL_RATE_DEGPS
#define BEEPTRIM_ROLL_RATE_DEGPS 0.2f
#endif
#ifndef FORCETRIMRELEASE_HOLD_TIME_MS
#define FORCETRIMRELEASE_HOLD_TIME_MS 1000.0f
#endif
#ifndef TRIMSYSTEM_SHEARPIN_BREAKINGFORCE_LBS
#define TRIMSYSTEM_SHEARPIN_BREAKINGFORCE_LBS 50.0f
#endif
¿Cuál es la razón fundamental de realizar estas comprobaciones de definición en lugar de simplemente definir las macros?
#define BEEPTRIM_PITCH_RATE_DEGPS 0.2f
#define BEEPTRIM_ROLL_RATE_DEGPS 0.2f
#define FORCETRIMRELEASE_HOLD_TIME_MS 1000.0f
#define TRIMSYSTEM_SHEARPIN_BREAKINGFORCE_LBS 50.0f
No puedo encontrar esta práctica explicada en ninguna parte de la web.
c
macros
c-preprocessor
ifndef
Trevor Hickey
fuente
fuente
Respuestas:
Esto le permite anular las macros cuando está compilando:
Las definiciones del archivo de encabezado se utilizan de forma predeterminada.
fuente
Como dije en el comentario, imagina esta situación:
foo.h
defs.h
bar.c
Imprimirá
44
.Sin embargo, si el condicional
ifndef
no estuviera allí, el resultado sería advertencias de compilación de redefinición de MACRO y se imprimirá64
.fuente
ifdef
para evitar redefinir).#infdef
s se utilizan como valores "alternativos" o "predeterminados". Básicamente, "si el usuario lo configuró, está bien. Si no, usemos un valor predeterminado".#defines
en una cabecera de biblioteca que forman parte de la biblioteca de la ABI, debería no envolverlos en#ifndef
. (O mejor, use unenum
). Solo quería dejar en claro que#ifndef
solo es apropiado cuando tener una definición personalizada para algo en una unidad de compilación, pero no en otra, está bien. Sia.c
incluye encabezados en un orden diferente al deb.c
, es posible que obtengan diferentes definiciones demax(a,b)
, y una de esas definiciones puede rompermax(i++, x)
, pero la otra puede usar temporales en una expresión-declaración de GNU. ¡Todavía confuso al menos!#ifdef FOO
#error FOO already defined!
#endif
#define FOO x
No conozco el contexto, pero esto se puede usar para darle al usuario la disponibilidad para anular los valores establecidos por esas definiciones de macro. Si el usuario define explícitamente un valor diferente para cualquiera de esas macros, se utilizará en lugar de los valores utilizados aquí.
Por ejemplo, en g ++ puede usar la
-D
bandera durante la compilación para pasar un valor a una macro.fuente
Esto se hace para que el usuario del archivo de encabezado pueda anular las definiciones de su código o del indicador -D del compilador.
fuente
Cualquier proyecto de C reside en varios archivos fuente. Cuando se trabaja en un solo archivo de origen, las comprobaciones parecen (y de hecho) no tienen sentido, pero cuando se trabaja en un proyecto C grande, es una buena práctica comprobar las definiciones existentes antes de definir una constante. La idea es simple: necesita la constante en ese archivo fuente específico, pero puede que ya esté definida en otro.
fuente
Podría pensar en un marco / biblioteca que le brinde al usuario un ajuste preestablecido predeterminado que le permita compilar y trabajar en él. Esas definiciones se distribuyen en diferentes archivos y se recomienda al usuario final que incluya su archivo config.h donde puede configurar sus valores. Si el usuario olvidó alguna definición, el sistema puede continuar funcionando debido a la configuración predeterminada.
fuente
Utilizando
permite al usuario definir el valor de la macro usando el argumento de la línea de comando (en gcc / clang / VS)
-DBEEPTRIM_PITCH_RATE_DEGPS=0.3f
.Hay otra razón importante. Es un error volver a definir una macro de preprocesador de manera diferente. Vea esta respuesta a otra pregunta SO . Sin la
#ifndef
verificación, el compilador debería producir un error si-DBEEPTRIM_PITCH_RATE_DEGPS=0.3f
se usa como argumento de línea de comando en la invocación del compilador.fuente