Em toda a nossa base de código C, vejo cada macro definida da seguinte maneira:
#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
Qual é a lógica de fazer essas verificações de definição em vez de apenas definir as 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
Não consigo encontrar essa prática explicada em nenhum lugar da web.
c
macros
c-preprocessor
ifndef
Trevor Hickey
fonte
fonte
Respostas:
Isso permite que você substitua as macros durante a compilação:
As definições no arquivo de cabeçalho são usadas como padrões.
fonte
Como disse no comentário, imagine esta situação:
foo.h
defs.h
bar.c
Irá imprimir
44
.No entanto, se a condicional
ifndef
não estivesse lá, o resultado seriam avisos de compilação de redefinição de MACRO e ela será impressa64
.fonte
ifdef
para evitar a redefinição).#infdef
s são usadas como valores "substitutos" ou "padrão". Basicamente, "se o usuário configurou, tudo bem. Se não, vamos usar um valor padrão."#defines
em um cabeçalho de biblioteca que fazem parte da ABI da biblioteca, você não deve envolvê-los#ifndef
. (Ou melhor, use umenum
). Eu só queria deixar claro que#ifndef
só é apropriado quando se tem uma definição personalizada para algo em uma unidade de compilação, mas não em outra, está ok. Sea.c
inclui cabeçalhos em uma ordem diferente deb.c
, eles podem obter diferentes definições demax(a,b)
, e uma dessas definições pode quebrarmax(i++, x)
, mas a outra pode usar temporários em uma expressão de instrução GNU. Ainda confuso, pelo menos!#ifdef FOO
#error FOO already defined!
#endif
#define FOO x
Eu não sei o contexto, mas isso pode ser usado para dar ao usuário a disponibilidade de substituir os valores definidos por essas definições de macro. Se o usuário definir explicitamente um valor diferente para qualquer uma dessas macros, ele será usado no lugar dos valores usados aqui.
Por exemplo, no g ++ você pode usar o
-D
sinalizador durante a compilação para passar um valor para uma macro.fonte
Isso é feito para que o usuário do arquivo de cabeçalho possa substituir as definições de seu código ou do sinalizador -D do compilador.
fonte
Qualquer projeto C reside em vários arquivos de origem. Ao trabalhar em um único arquivo de origem, as verificações parecem (e na verdade) não têm sentido, mas ao trabalhar em um grande projeto C, é uma boa prática verificar as definições existentes antes de definir uma constante. A ideia é simples: você precisa da constante naquele arquivo fonte específico, mas pode já ter sido definida em outro.
fonte
Você poderia pensar em uma estrutura / biblioteca que dá ao usuário uma predefinição padrão que permite ao usuário compilar e trabalhar nela. Essas definições estão espalhadas em arquivos diferentes e o usuário final é aconselhado a incluir seu arquivo config.h onde ele pode configurar seus valores. Se o usuário esqueceu alguma definição, o sistema pode continuar a funcionar por causa da predefinição.
fonte
Usando
permite ao usuário definir o valor da macro usando o argumento da linha de comando (em gcc / clang / VS)
-DBEEPTRIM_PITCH_RATE_DEGPS=0.3f
.Existe outro motivo importante. É um erro redefinir uma macro do pré-processador de maneira diferente. Veja esta resposta a outra pergunta do SO . Sem a
#ifndef
verificação, o compilador deve produzir um erro se-DBEEPTRIM_PITCH_RATE_DEGPS=0.3f
for usado como um argumento de linha de comando na chamada do compilador.fonte