我正在获取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)) ) )
但是根据我的理解,在转换操作的情况下,将unsigned转换为unsigned可能不是一个好主意。
需要一些帮助...
答案 0 :(得分:1)
这整个代码绝对不符合MISRA-C标准。
首先,有一些不太重要的挑选。指令4.9表示应该完全避免使用类似函数的宏。规则7.2表示必须对所有整数常量使用u
后缀。
这里最严重的是违反10.1,其中说&#34;移位和按位操作只应在基本上无符号类型的操作数上执行&#34; 。
你左移一个带符号的操作数 - 如果该操作数是否定的,你的代码会调用未定义的行为并且你有一个严重的错误。然后,您还右移一个带符号的操作数,如果操作数为负,则调用实现定义的行为。这些不只是一些误报,而是你必须解决的实际错误。最简单的解决方法是在任何转移之前将x
投射到uint64_t
。
我认为没有违反10.5的规定,这会违反不合适的类型。从签名到无签名都可以。
然而,您的评论表明存在违反10.8的规定 - 该规则不允许&#34;复合表达式的结果&#34;根据您的情况,从sint64_t
到uint64_t
或uint32_t
转换为其他类型类别。这也可以通过在做其他事情之前转换为uint64_t
来解决。
10.8的(相当奇怪的)基本原理是,一些初学者认为像(uint32_t)(u16a + u16b);
这样的演员表示+操作是在uint32_t
上执行的,这是不正确的。
现在真正的问题是所有这些转变实际上是要开始实现的;这对我来说并不清楚。宏非常混乱。如果意图清除变量的某些位,则应使用位屏蔽(按位&
)来完成。如果必须使用原因未知的签名变量并且必须保留符号,则位掩码可以简单地跳过符号位。
修复此代码的最佳方法是完全重写该宏。目前,它永远不会通过MISRA-C,这是一件好事。