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

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


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

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 используется в качестве аргумента командной строки при вызове компилятора.