为什么只定义一个尚未定义的宏?
Why only define a macro if it's not already defined?
在我们的所有 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
我在网络上的任何地方都找不到对这种做法的解释。
我不知道上下文,但这可以用来让用户可以覆盖那些宏定义设置的值。如果用户为这些宏中的任何一个显式定义了一个不同的值,它将被使用而不是这里使用的值。
例如,在 g++ 中,您可以在编译期间使用 -D
标志将值传递给宏。
这样做是为了让头文件的用户可以覆盖来自 his/her 代码或来自编译器的 -D 标志的定义。
这允许您在编译时覆盖宏:
gcc -DMACRONAME=value
头文件中的定义用作默认值。
任何 C 项目都驻留在多个源文件中。当处理单个源文件时,检查似乎(实际上)没有意义,但是当处理大型 C 项目时,在定义常量之前检查现有定义是一个很好的做法。这个想法很简单:您需要那个特定源文件中的常量,但它可能已经在另一个源文件中定义了。
正如我在评论中所说,想象一下这种情况:
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
^
您可以考虑 framework/library 为用户提供默认预设,允许用户对其进行编译和处理。
这些定义分布在不同的文件中,建议最终用户包含它的 config.h 文件,他可以在其中配置其值。
如果用户忘记了一些定义系统可以继续工作因为预设。
正在使用
#ifndef BEEPTRIM_PITCH_RATE_DEGPS
#define BEEPTRIM_PITCH_RATE_DEGPS 0.2f
#endif
允许用户使用命令行参数定义宏的值(在 gcc/clang/VS 中)-DBEEPTRIM_PITCH_RATE_DEGPS=0.3f
.
还有一个重要的原因。以不同的方式重新定义预处理器宏是错误的。参见 this answer to another SO question。如果没有 #ifndef
检查,如果 -DBEEPTRIM_PITCH_RATE_DEGPS=0.3f
在编译器调用中用作命令行参数,编译器应该会产生错误。
在我们的所有 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
我在网络上的任何地方都找不到对这种做法的解释。
我不知道上下文,但这可以用来让用户可以覆盖那些宏定义设置的值。如果用户为这些宏中的任何一个显式定义了一个不同的值,它将被使用而不是这里使用的值。
例如,在 g++ 中,您可以在编译期间使用 -D
标志将值传递给宏。
这样做是为了让头文件的用户可以覆盖来自 his/her 代码或来自编译器的 -D 标志的定义。
这允许您在编译时覆盖宏:
gcc -DMACRONAME=value
头文件中的定义用作默认值。
任何 C 项目都驻留在多个源文件中。当处理单个源文件时,检查似乎(实际上)没有意义,但是当处理大型 C 项目时,在定义常量之前检查现有定义是一个很好的做法。这个想法很简单:您需要那个特定源文件中的常量,但它可能已经在另一个源文件中定义了。
正如我在评论中所说,想象一下这种情况:
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
^
您可以考虑 framework/library 为用户提供默认预设,允许用户对其进行编译和处理。 这些定义分布在不同的文件中,建议最终用户包含它的 config.h 文件,他可以在其中配置其值。 如果用户忘记了一些定义系统可以继续工作因为预设。
正在使用
#ifndef BEEPTRIM_PITCH_RATE_DEGPS
#define BEEPTRIM_PITCH_RATE_DEGPS 0.2f
#endif
允许用户使用命令行参数定义宏的值(在 gcc/clang/VS 中)-DBEEPTRIM_PITCH_RATE_DEGPS=0.3f
.
还有一个重要的原因。以不同的方式重新定义预处理器宏是错误的。参见 this answer to another SO question。如果没有 #ifndef
检查,如果 -DBEEPTRIM_PITCH_RATE_DEGPS=0.3f
在编译器调用中用作命令行参数,编译器应该会产生错误。