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_t
到 uint64_t
或 uint32_t
。这也可以通过在 做任何其他事情之前转换为 uint64_t
来解决。
10.8 的(相当奇怪的)理由是一些初学者认为像 (uint32_t)(u16a + u16b);
这样的转换意味着 + 操作在 uint32_t
上执行,这是不正确的。
现在真正的问题是所有这些转变实际上是为了什么而开始的;我不清楚。宏相当混乱。如果打算清除变量的某些位,则应使用位掩码(按位 &
)来完成。并且如果必须使用未知符号变量并且必须保留符号的原因,位掩码可以简单地跳过符号位。
修复此代码的最佳方法是完全重写该宏。就目前而言,它永远不会通过 MISRA-C,这是一件好事。
我遇到了 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_t
到uint64_t
或uint32_t
。这也可以通过在 做任何其他事情之前转换为uint64_t
来解决。10.8 的(相当奇怪的)理由是一些初学者认为像
(uint32_t)(u16a + u16b);
这样的转换意味着 + 操作在uint32_t
上执行,这是不正确的。
现在真正的问题是所有这些转变实际上是为了什么而开始的;我不清楚。宏相当混乱。如果打算清除变量的某些位,则应使用位掩码(按位 &
)来完成。并且如果必须使用未知符号变量并且必须保留符号的原因,位掩码可以简单地跳过符号位。
修复此代码的最佳方法是完全重写该宏。就目前而言,它永远不会通过 MISRA-C,这是一件好事。