头文件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
中有标志可以做到这两点。
答案 0 :(得分:1)
每当在#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
选项变成一个完整的错误。
答案 1 :(得分:1)
总之,基本问题似乎是armcc
C预处理器/编译器没有选项来警告在#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 );
或常量或表达式,而不是my_red
,my_green
和my_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
等符号视为未定义。