关于缺少预处理器符号的编译器警告

时间:2015-01-23 08:58:39

标签: c c-preprocessor preprocessor-directive

背景

我有 C 项目,它有一个配置头文件,例如:

// config.h
#define FEATURE_1_AVAILABLE      1
#define FEATURE_2_AVAILABLE      0
#define FEATURE_3_AVAILABLE      1

模块使用这些标志来包含/排除build中的功能:

#include "config.h"
void foo(void) {
    ...
    #if FEATURE_1_AVAILABLE
    useFeature1();
    #endif
    ...

不同版本的config.h版本有不同版本。

问题

#include "config.h"被意外删除,因此功能即使在配置中启用也无法激活。

不幸的是,#if FEATURE_1_AVAILABLE在未定义时会默默评估为0。如果没有定义,我需要一个错误。

选项1

我可以添加额外的'如果已定义'测试每种情况。

#ifndef FEATURE_1_AVAILABLE
    #error No feature 1  
#elif FEATURE_1_AVAILABLE
    useFeature1();
#endif

缺点是可以在模块中的多个不同位置测试一个功能标志,并且添加多个预处理器行不会使代码更漂亮。

选项2

在模块的开头添加单个测试:

#ifndef FEATURE_1_AVAILABLE
    #error  No feature 1  
#endif

但由于与#include "config.h"相同的原因,这可能会丢失/遗忘。

选项3

将标志定义为宏:

#define FEATURE_1_AVAILABLE()      1

并用作:

#if FEATURE_1_AVAILABLE()

不幸的是,如果你忘了括号,这也会无声地失败:

#if FEATURE_1_AVAILABLE

选项X

有更好的选择吗?如果未定义符号或未正确写入符号,则会在编译时给出错误消息。并且希望不会使代码看起来不可维护的预处理程序混乱。

其他事项

  • 无法进行运行时检查。禁用的功能不得为二进制文件。
  • 必须在文件中定义功能。将它们定义为全局编译器选项还有其他问题。
  • 这适用于嵌入式系统。其中一些功能需要硬件才能工作,测试非常耗时。因此,首选编译错误。

2 个答案:

答案 0 :(得分:4)

另一种解决方案是让编译器在未定义被评估的宏时发出警告。

例如,gcc-Wundef选项(未包含在-Wall中):

#if FEATURE_1_AVAILABLE
useFeature1();
#endif

这会发出警告(添加-Werror以使其成为错误):

tst.c:6:9: warning: "FEATURE_1_AVAILABLE" is not defined [-Wundef]
     #if FEATURE_1_AVAILABLE

此选项也适用于其他编译器,例如: g。,clangicc

答案 1 :(得分:0)

我知道它是being frowned upon,但对于较小的C项目,使用一个项目范围的包含文件(例如myproject.h)与您的{{{{{ 1}}指令(如#include ..),然后在每个源文件的顶部只有 #include "config.h"

意外忘记这个单#include "myproject.h通常会立即破坏编译,因此不会被忽视。

或者,您可以在#include(并且只在那里)放置一个必要的#include(比如#include assert.h),再次在您忘记包含它时惹恼编译器/链接器< / p>