IAR 编译器警告:"macro does not create a valid token"

IAR Compiler warning: "macro does not create a valid token"

我用C写了下面的宏:

#define __HAL_CLK_ENABLE(CONTROL_STRUCT,REG,CLK) do { \
SET_BIT(CONTROL_STRUCT->REG,##CONTROL_STRUCT##_##REG##_##CLK##EN);\
} while(0)

main.c中的宏调用/所有参数在cpu特定头文件中定义:

__HAL_CLK_ENABLE(RCC,AHB1ENR,GPIOA);

结果应该是:

SET_BIT(RCC->AHB1ENR,RCC_AHB1ENR_GPIOAEN)

这个宏可以正常工作并正确启用我的 GPIOA 端口,但我收到两个编译器警告。 (IAR EW 7.6)

  1. macro 参数 "CONTROL_STRUCT" 用于扩展和原始形式。 (我会忽略这个警告,因为在这种情况下使用两种形式都是正确的!)

2。在宏“__HAL_CLK_ENABLE”中与 "RCC_AHB1ENR_GPIOAEN" 连接不会创建有效标记。 (什么意思?因为token正常工作,调用这个宏后我的时钟开启了)

谢谢

编辑 1:

宏定义:

#define SET_BIT(REG, BIT)     ((REG) |= (BIT))

#define RCC                 ((RCC_TypeDef *) RCC_BASE)

typedef struct
{
...                        
__IO uint32_t AHB1ENR;
...
} RCC_TypeDef;

#define GPIOA               ((GPIO_TypeDef *) GPIOA_BASE)

##CONTROL_STRUCT##_##REG##_##CLK##EN中删除第一个##

请注意,您的操作容易出错,嵌入式编码标准不推荐这样做。

米斯拉 C:

Rule 19.12 (required): There shall be at most one occurrence of the # or ## operators in a single macro definition.


Rule 19.13 (advisory): The # and ## operators should not be used.

“# 和 ## 运算符的计算顺序未指定。” (ISO C99/C11 6.10.3.2, 6.10.3.3) 这意味着宏可能会导致程序员无法使用一种编译器而不是另一种编译器。

在你的情况下,这没什么大不了的,正如 Ouss4 提到的,MISRA-C 建议不要使用多个 # 或 ## 运算符,主要是为了避免混淆(因此它只是一个建议指南)。

然而,如果 ## 操作导致无效令牌,它可能的多个 ## 运算符 可能 会导致未定义的行为,这就是 IAR 警告的内容。这个和一个简单的例子在 MISRA-C 论坛上讨论 "Rule 19.12 (# and ## operator) real issue?” :

define m(a,b) a##.##b

m(1,e30)

which is defined behavior on a left-to-right evaluation but undefined behavior on right-to-left because .e30 is two preprocessing tokens.