2

头文件config.h包含以下语句:

#define RED 0
#define BLUE 1
#define GREEN 2
#define CONFIG_COLOR RED

源文件main.c不包括config.h包含以下内容:

#if CONFIG_COLOR == RED
/* Red code */
#elif CONFIG_COLOR == BLUE
/* Blue code */
#elif CONFIG_COLOR == GREEN
/* Green code */
#endif

ARM 编译器ARMCC(或者更确切地说,C 预处理器)在编译时不会发出任何警告或错误,main.c尽管CONFIG_COLOR没有定义。

有没有办法强制编译器在上述情况下发出错误?

或者,有没有办法强制 Keil ARM uVision IDE 始终包含config.h每个源文件?

我知道GCC有旗帜可以做到这两点。

4

2 回答 2

2

每当一个符号没有在#if/#elif指令中定义时,它就被简单地替换为0. 因此,如果CONFIG_COLOR未定义,您的代码与以下内容相同:

#if 0 == RED
/* Red code */
#elif 0 == BLUE
/* Blue code */
#elif 0 == GREEN
/* Green code */
#endif

例如,如果RED定义为0,这可能会导致可怕的错误,因此第一个条件变为真。CONFIG_COLOR如果未通过以下方式定义,您可以有条件地停止编译并出现错误#error

#ifndef CONFIG_COLOR
    #error CONFIG_COLOR is not defined!
#endif

您还可以让 GCC/Clang-Wl,-Wundef选择在发生这种情况时发出警告。这可以通过-Wl,-Werror选项变成一个全面的错误。

于 2017-02-06T17:32:36.583 回答
1

总而言之,潜在的问题似乎是armccC 预处理器/编译器没有选项来警告是否在#if预处理器指令中使用了未定义的预处理器宏,并且下游开发人员需要提示才能使他们的代码正常工作。


正如我在评论中提到的,我的第一直觉是使用预处理器宏来指示是否选择了一种颜色,而不是选择了哪种颜色。在这种情况下,代码块变成

#if defined(CONFIG_COLOR_IS_RED)
/* Red case */
#elif defined(CONFIG_COLOR_IS_GREEN)
/* Green case */
#elif defined(CONFIG_COLOR_IS_BLUE)
/* Blue case */
#else
#error config.h is not included!
#endif

当然,下游开发人员必须包括整个区块。(这似乎是 OP 的一个问题;下游者可能会忘记或错误编辑该块。)


另一种选择是在表达式级别(而不是块级别)进行选择;即使用宏

CONFIG_COLOR(red-expression, green-expression, blue-expression)

其定义config.h为,例如,

#if   defined(CONFIG_COLOR_IS_RED)
#define CONFIG_COLOR(red, green, blue) (red)
#elif defined(CONFIG_COLOR_IS_GREEN)
#define CONFIG_COLOR(red, green, blue) (green)
#elif defined(CONFIG_COLOR_IS_BLUE)
#define CONFIG_COLOR(red, green, blue) (blue)
#else
#error Color not configured!
#endif

在这种情况下,如果不包含头文件,编译器应在编译时警告未声明的符号CONFIG_COLOR,并在链接时拒绝链接,因为符号CONFIG_COLOR未定义。

在这种情况下,用户代码非常简单,例如

my_color_attribute = CONFIG_COLOR( my_red, my_green, my_blue );

or 常量或表达式,而不是my_red,my_greenmy_blue. 如您所见,宏从三个值中选择一个值,具体取决于选择的“颜色”。


如果需要块级代码,那么我建议使用宏

IF_RED
    /* Red case */
ENDIF
IF_GREEN
    /* Green case */
ENDIF
IF_BLUE
    /* Blue case */
ENDIF

其中宏定义config.h为例如

#if   defined(COLOR_IS_RED)
#define IF_RED   if (1) {
#define IF_GREEN if (0) {
#define IF_BLUE  if (0) {
#elif defined(COLOR_IS_GREEN)
#define IF_RED   if (0) {
#define IF_GREEN if (1) {
#define IF_BLUE  if (0) {
#elif defined(COLOR_IS_BLUE)
#define IF_RED   if (0) {
#define IF_GREEN if (0) {
#define IF_BLUE  if (1) {
#else
#error Color not selected!
#endif
#define END_IF   }

它为未选择的代码案例生成失效代码(永远不会到达的代码);编译器应该能够优化分支,尽管我不确定armcc.

如果config.h不包含头文件,则编译器会将IF_RED等符号阻塞为未定义。

于 2017-02-06T17:59:05.983 回答