MISRA-C 2012 规则 10.8 查询

MISRA-C 2012 Rule 10.8 Query

我遇到了 MISRA-C 2012 规则 10.5 错误,下面是示例代码:

+++++++++++++++++++++++++++++++++++++++++++++ +++++++++++++++++++++++++++++++

typedef long long       sint64; 
typedef unsigned long long  uint64;
typedef unsigned long   uint32;

#define ntohll(x) ( ( (uint64)(ntohl( ((x << 32) >> 32) )) << 32) | ntohl( ((uint32)(x >> 32)) ) )

void main()
{
 sint64 pul_total;
 sint64 a;
 pul_total = ntohll(a); /* Rule 10.8 Violation*/    
}

+++++++++++++++++++++++++++++++++++++++++++++ +++++++++++++++++++++++++++++++ 解决我在下面尝试过的问题:

#define ntohll(x) ( ( (uint64)(ntohl( ((x << 32) >>(uint32)32) )) << (uint32)32) | ntohl( ((uint32)(x >>(uint32) 32)) ) )

但仍然是一种浪费

但是,如果我按照以下方式进行操作,违规行为将被删除:

  #define ntohll(x) ( ( (uint64)(ntohl( ((x << 32) >> 32) )) << 32) | ntohl( ((uint32)((uint32)x >> 32)) ) )

但根据我的理解,在移位操作的情况下,将有符号变量转换为无符号变量可能不是一个好主意。

同样需要一些帮助...

整个代码绝对不符合 MISRA-C。

  • 首先有一些不太重要的挑剔。指令 4.9 说应该完全避免类似函数的宏。规则 7.2 说你必须在所有整数常量上使用 u 后缀。

  • 这里最严重的是违反了 10.1,它说“移位和按位运算只能在 基本无符号类型 的操作数上执行”。

    您左移了一个带符号的操作数 - 如果该操作数为负,您的代码将调用未定义的行为并且您有一个严重的错误。然后,您还右移一个带符号的操作数,如果操作数为负,则调用实现定义的行为。这些不仅仅是一些误报,而是您必须修复的实际错误。最简单的解决方法是在任何移位之前将 x 转换为 uint64_t

  • 我没有发现违反 10.5 的情况,这将转换为不合适的类型。可以从有符号转换为无符号。

  • 然而,如您的评论所示,存在违反 10.8 的情况 - 该规则不允许将“复合表达式”的结果转换为不同的类型类别,在您的情况下来自 sint64_tuint64_tuint32_t。这也可以通过在 做任何其他事情之前转换为 uint64_t 来解决。

    10.8 的(相当奇怪的)理由是一些初学者认为像 (uint32_t)(u16a + u16b); 这样的转换意味着 + 操作在 uint32_t 上执行,这是不正确的。

现在真正的问题是所有这些转变实际上是为了什么而开始的;我不清楚。宏相当混乱。如果打算清除变量的某些位,则应使用位掩码(按位 &)来完成。并且如果必须使用未知符号变量并且必须保留符号的原因,位掩码可以简单地跳过符号位。

修复此代码的最佳方法是完全重写该宏。就目前而言,它永远不会通过 MISRA-C,这是一件好事。