3

这段代码报告了三个 misrac 错误:

  1. 不恰当的宏展开
  2. 类函数宏定义
  3. 不带括号的宏参数

原始代码是:

#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 错误。

4

2 回答 2

6

1.不恰当的宏展开

这是因为您没有正确封装宏。要解决此问题,您必须将代码更改为:

#define Wait(a, b)                         \
                                           \
do {                                       \
  if (READ(b+0x1U))                        \
  {                                        \
    while ((a & Write(b)))                 \
    {                                      \
        /* Do nothing - Busy wait */       \
    }                                      \
  }                                        \
} while (0);

(当然,如果你的其余代码遵循 MISRA-C 并且总是{}在 every if, fororwhile语句之后使用,那么这是毫无意义的练习。)


2.Function-like宏定义

您正在使用类似函数的宏。MISRA-C 不允许这样做。将宏重写为函数。

但是,规则 19.7 是建议性的,因此理论上您可以忽略它而不会引起偏差。但在这种情况下没有理由这样做。没有理由为什么这需要是一个宏而不是一个函数。


3.不带括号的宏参数

如您所料,这与每个宏参数都是潜在的子表达式有关。假设有人将您的宏称为Wait(x+y, z). 然后,您的代码将在遇到 while 循环时崩溃并烧毁,因为宏将扩展为while(x+y & Write(b)),这与while(x + (y & Write(b)) ).

要解决这个问题,请用括号括起来a和的每个实例,如第二个示例所示。b


这段代码报告了三个 misrac 错误:

您应该向 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最好写成0ULor 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 */
        }
      }
    }
    
于 2013-12-10T12:37:51.233 回答
3

有一个宏允许扩展的列表,而 if 块不是其中之一。我相信这是因为它可能会导致对 else 子句的附加造成混淆。 更多关于这里。 您可以使用此构造:

#define MACRO(X)    \
do {                \
    body here       \
} while (0)

您应该尽可能使用函数而不是类似函数的宏。在不知道 READ 扩展到什么的情况下,我不能说在这种情况下是否可能。那将是摆脱有关警告的唯一方法。

第三个你已经想通了;您必须在正文中a和周围加上括号。b这里的想法是,如果您有x*2宏中的代码并且有人传递3+1为 x,没有括号,您将得到3+1*25,而不是(3+1)*28,这几乎可以肯定是有意的。

关于你的代码,我唯一要说的另一件事是你确定你想要&那里而不是&&

于 2013-12-09T19:24:54.747 回答