94

在我们的 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

我在网络上的任何地方都找不到这种做法的解释。

4

7 回答 7

142

这允许您在编译时覆盖宏:

gcc -DMACRONAME=value

头文件中的定义用作默认值。

于 2015-09-04T12:58:15.833 回答
51

正如我在评论中所说,想象一下这种情况:

foo.h

#define FOO  4

定义文件

#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不存在,结果将是 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
 ^
于 2015-09-04T13:02:27.980 回答
17

我不知道上下文,但这可用于让用户可以覆盖这些宏定义设置的值。如果用户为这些宏中的任何一个显式定义不同的值,它将被使用而不是此处使用的值。

例如,在 g++ 中,您可以-D在编译期间使用标志将值传递给宏。

于 2015-09-04T12:57:29.147 回答
14

这样做是为了让头文件的用户可以覆盖他/她的代码或编译器的 -D 标志中的定义。

于 2015-09-04T12:58:08.590 回答
7

任何 C 项目都驻留在多个源文件中。在处理单个源文件时,检查似乎(实际上)没有意义,但是在处理大型 C 项目时,在定义常量之前检查现有定义是一种很好的做法。这个想法很简单:您需要该特定源文件中的常量,但它可能已经在另一个源文件中定义。

于 2015-09-04T12:59:39.010 回答
2

您可以考虑一个框架/库,它为用户提供一个默认预设,允许用户对其进行编译和处理。这些定义分布在不同的文件中,建议最终用户将其包含在 config.h 文件中,他可以在其中配置其值。如果用户忘记了一些定义,系统可以因为预设而继续工作。

于 2015-09-04T13:08:31.683 回答
1

使用

#ifndef BEEPTRIM_PITCH_RATE_DEGPS
#define BEEPTRIM_PITCH_RATE_DEGPS                   0.2f
#endif

允许用户使用命令行参数(在 gcc/clang/VS 中)定义宏的值-DBEEPTRIM_PITCH_RATE_DEGPS=0.3f

还有一个重要原因。以不同方式重新定义预处理器宏是错误的。请参阅另一个 SO question 的答案。如果没有检查,如果在编译器调用中用作命令行参数,#ifndef编译器应该会产生错误。-DBEEPTRIM_PITCH_RATE_DEGPS=0.3f

于 2015-09-09T00:34:20.310 回答