Почему только определить макрос, если он еще не определен?


по всей нашей базе кода 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

Я не могу найти эту практику объяснить в интернете.

7 90

7 ответов:

Это позволяет переопределить макросы при компиляции:

gcc -DMACRONAME=value

определения в заголовочном файле используются по умолчанию.

как я сказал в комментарии, представьте себе такую ситуацию:

фу.h

#define FOO  4

defs.h

#ifndef FOO
#define FOO 6
#endif

#ifndef BAR
#define BAR 4
#endif

бар.c

#include "foo.h"
#include "defs.h"

#include <stdio.h>

int main(void)
{
    printf("%d%d", FOO, BAR);
    return 0;
}

печати 44.

однако, если условный ifndef не было там, результатом будет компиляция предупреждений о переопределении макроса, и он будет печатать 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 рекомендуется проверять существующие определения перед определением константы. Идея проста: вам нужна константа в этом конкретном исходном файле, но она может быть уже определена в другом.

вы можете подумать о фреймворке / библиотеке, которая дает пользователю предустановку по умолчанию, которая позволяет пользователю компилировать и работать над ней. Эти определения распространяются в разных файлах, и конечному пользователю рекомендуется включить его конфигурацию.H файл, где он может настроить свои значения. Если пользователь забыл некоторые определения система может продолжать работать из-за настроек.

используя

#ifndef BEEPTRIM_PITCH_RATE_DEGPS
#define BEEPTRIM_PITCH_RATE_DEGPS                   0.2f
#endif

позволяет пользователю определить значение макроса с помощью аргумента командной строки (в gcc/clang/VS) -DBEEPTRIM_PITCH_RATE_DEGPS=0.3f.

есть еще одна важная причина. Это ошибка, чтобы переопределить макрос препроцессора по-другому. Смотрите это ответ на другой вопрос так. Без #ifndef проверьте, компилятор должен выдать ошибку, если -DBEEPTRIM_PITCH_RATE_DEGPS=0.3f используется в качестве аргумента командной строки при вызове компилятора.