Ответ 1
Это позволяет вам переопределять макросы при компиляции:
gcc -DMACRONAME=value
Определения в файле заголовка используются как значения по умолчанию.
Всю нашу базу кода C, я вижу, что каждый макрос определяется следующим образом:
#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
В чем обоснование этих определений определяет проверки вместо простого определения макросов?
#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
Я не могу найти эту практику в любом месте в Интернете.
Это позволяет вам переопределять макросы при компиляции:
gcc -DMACRONAME=value
Определения в файле заголовка используются как значения по умолчанию.
Как я сказал в комментарии, представьте эту ситуацию:
foo.h
#define FOO 4
defs.h
#ifndef FOO
#define FOO 6
#endif
#ifndef BAR
#define BAR 4
#endif
bar.c
#include "foo.h"
#include "defs.h"
#include <stdio.h>
int main(void)
{
printf("%d%d", FOO, BAR);
return 0;
}
Будет напечатан 44
.
Однако, если условного ifndef
не было, результат был бы предупреждением компиляции переопределения MACRO, и он напечатает 64
.
$ gcc -o bar bar.c
In file included from bar.c:2:0:
defs.h:1:0: warning: "FOO" redefined [enabled by default]
#define FOO 6
^
In file included from bar.c:1:0:
foo.h:1:0: note: this is the location of the previous definition
#define FOO 4
^
Я не знаю контекста, но это можно использовать, чтобы дать пользователю возможность переопределить значения, установленные этими макроопределениями. Если пользователь явно определяет другое значение для любого из этих макросов, он будет использоваться вместо значений, используемых здесь.
Например, в g++ вы можете использовать флаг -D
во время компиляции, чтобы передать значение макросу.
Это делается для того, чтобы пользователь файла заголовка мог переопределить определения из своего кода или из флага компилятора -D.
Любой проект C находится в нескольких исходных файлах. При работе с одним исходным файлом проверки, кажется, (и фактически) не имеют смысла, но при работе над крупным проектом C рекомендуется проверять существующие определения перед определением константы. Идея проста: вам нужна константа в этом конкретном исходном файле, но она, возможно, уже определена в другом.
Вы можете подумать о структуре/библиотеке, которая предоставляет пользователю предустановленную по умолчанию пресет, позволяющую пользователю компилировать и работать с ней. Эти определения распространяются в разных файлах, и конечному пользователю рекомендуется включить его в файл config.h, где он может настроить свои значения. Если пользователь забыл некоторые, то система может продолжать работать из-за пресета.
Использование
#ifndef BEEPTRIM_PITCH_RATE_DEGPS
#define BEEPTRIM_PITCH_RATE_DEGPS 0.2f
#endif
позволяет пользователю определять значение макроса с помощью аргумента командной строки (в gcc/clang/VS) -DBEEPTRIM_PITCH_RATE_DEGPS=0.3f
.
Есть еще одна важная причина. Ошибка переопределить макрос препроцессора по-разному. См. этот ответ на другой вопрос SO. Без проверки #ifndef
компилятор должен произвести ошибку, если -DBEEPTRIM_PITCH_RATE_DEGPS=0.3f
используется как аргумент командной строки при вызове компилятора.