宏定义中的Misra C错误

时间:2013-12-09 18:50:28

标签: c macros misra

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

  1. 不恰当的宏观扩张
  2. 类似函数的宏定义
  3. 没有括号的宏参数
  4. 原始代码是:

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

2 个答案:

答案 0 :(得分:5)

  

1.不适当的宏观扩张

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

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

(但是,如果您的其余代码遵循MISRA-C并且在每个{}iffor语句后始终使用while,那么这是毫无意义的练习。)


  

2.类似功能的宏定义

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

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


  

3.没有括号的宏参数

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

要解决此问题,请使用括号括起ab的每个实例,如第二个示例所示。


  

这段代码报告了三个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最好应写为0UL0ul,这些表格更具可读性。
  • 坦率地说,这段代码开头不好。试图使其符合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扩展到什么我不能说在这种情况下是否可能。这将是摆脱警告的唯一方法。

你已经想到的第三个;你必须在ab周围加上括号。这里的想法是,如果您在宏中使用x*2之类的代码,并且有人将3+1作为x传递,则不使用括号,您将得到3+1*2,即5,而不是{{ 1}},这几乎可以肯定是8。

关于您的代码,我唯一要说的是您确定要(3+1)*2而不是&吗?