总而言之,潜在的问题似乎是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 );
or 常量或表达式,而不是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
等符号阻塞为未定义。