这段代码报告了三个misra c错误:
原始代码是:
#define Wait(a, b) \
if (READ(b+0x1U)) \
{ \
while ((a & Write(b))) \
{ \
/* Do nothing - Busy wait */ \
} \
}
Here READ(b) is a macro and Write(b) is a function with no Misra C error.
我尝试更改它以删除错误
#define Wait(a, b) \
if ((uint32_t)0U != READ((b)+0x1U)) \
{ \
while ((uint32_t)0U != ((uint32_t)(a) & Write((uint32_t)(b)))) \
{ \
/* Do nothing - Busy wait */ \
} \
}
但我仍然得到前两个错误。需要做些什么来消除这些Misra C错误。
答案 0 :(得分:5)
1.不适当的宏观扩张
这是因为您没有正确封装宏。要解决此问题,您必须将代码更改为:
#define Wait(a, b) \
\
do { \
if (READ(b+0x1U)) \
{ \
while ((a & Write(b))) \
{ \
/* Do nothing - Busy wait */ \
} \
} \
} while (0);
(但是,如果您的其余代码遵循MISRA-C并且在每个{}
,if
或for
语句后始终使用while
,那么这是毫无意义的练习。)
2.类似功能的宏定义
您正在使用类似函数的宏。 MISRA-C不允许这样做。将宏重写为函数。
然而,规则19.7是建议性的,所以你理论上可以忽略它而不会引起偏差。但在这种情况下没有理由这样做。没有理由认为这需要是一个宏而不是一个函数。
3.没有括号的宏参数
正如您所猜测的,这与每个宏参数都是潜在的子表达式有关。假设有人将您的宏称为Wait(x+y, z)
。然后,您的代码会在遇到while循环时崩溃并烧毁,因为宏将扩展为while(x+y & Write(b))
,这与while(x + (y & Write(b)) )
相同。
要解决此问题,请使用括号括起a
和b
的每个实例,如第二个示例所示。
这段代码报告了三个misra c错误:
您应该向Klockwork报告错误,他们的工具无法正常工作。它还应该检测到以下内容:
if (READ(b+0x1U))
违反规则13.2。符合MISRA的代码将是
if (READ(b+0x1U) != 0u)
while ((a & Write(b)))
违反了规则13.2。符合MISRA的代码将是
while ( (a & Write(b)) != 0u )
非MISRA相关问题:
(uint32_t)0U
最好应写为0UL
或0ul
,这些表格更具可读性。坦率地说,这段代码开头不好。试图使其符合MISRA标准,将其变成一个完全不可读的混乱。改为从头开始重写:
void Wait (uint32_t a, uint32 b)
{
if( READ(b + 0x1u) != 0u ) /* comment here, explaining the code */
{
while ( (a & Write(b)) != 0u ) /* comment here, explaining the code */
{
; /* Do nothing - busy wait */
}
}
}
答案 1 :(得分:3)
有一个允许宏扩展到的东西的列表,而if块不是其中之一。我相信这是因为它可能会引起对其他条款附件的混淆。 More about that here.您可以使用此构造:
#define MACRO(X) \
do { \
body here \
} while (0)
您应该尽可能使用函数而不是函数式宏。不知道READ扩展到什么我不能说在这种情况下是否可能。这将是摆脱警告的唯一方法。
你已经想到的第三个;你必须在a
和b
周围加上括号。这里的想法是,如果您在宏中使用x*2
之类的代码,并且有人将3+1
作为x传递,则不使用括号,您将得到3+1*2
,即5,而不是{{ 1}},这几乎可以肯定是8。
关于您的代码,我唯一要说的是您确定要(3+1)*2
而不是&
吗?