理解Klocwork位运算符号
Understand Klocwork bitwise operation sign
当被klocwork分析时,下面一行
pTxData[index] = ( UINT8_C(0) << UINT8_C(4) );
给出错误
Operand of bitwise operation has type 'signed char' instead of
'unsigned integer'
我已经通过删除任何 #define
将问题减少到最低限度,并且完全不知道为什么会发生这种情况。
在大多数表达式中,排名小于 int
的整数类型被转换为 int
(如果 int
可以无损失地表示所有值)或 unsigned int
(否则)。
为了简化一点,考虑等级对应于类型中的位数,位数越多,等级越高(对于术语的明确处理,请参阅语言参考(例如,您可能开始 here)).
这里似乎是这种情况,UINT8_C()
(可能是 unsigned char
伪装)返回的类型比 int
的级别小,所以你最终得到了一个签名类型。
现在,出现警告的原因是在所有情况下都没有很好地定义移位有符号整数类型。向左移动负值或在移动时溢出相当于 未定义的行为 ,这意味着如果遇到这两种情况中的任何一种,程序可能会以多种方式出现异常行为。 (在移动无符号类型时溢出是合法的,你会得到一个截断的值)。
此外,班次计数不能为负数。
但是,如果这是确切的代码,则警告是不必要的,因为显然将 0 向左移动 4 个位置是完全安全的。如果您使用变量而不是常量,编译器(或工具)将不会总是能够推断出这种转变的安全性,在这种情况下,您应该注意警告并以这样一种方式重写您的代码,即未定义的行为或警告。
对于那些不知道的人,UINT8_C
是一个 C 标准宏1) 用于获取 uint_least8_t
类型的整数常量而不是默认的 [=13] =].
因此 UINT8_C(0)
等同于 (uint_least8_t)0
。这将是一个小整数类型。因此,当作为左操作数传递给 <<
时,它会受到整数提升 2) 的影响。提升后它最终成为 int
类型,相当于只写 0
.
切勿将带符号的操作数与按位运算符一起使用,因此这是错误消息的核心原因。更正后的代码应类似于 0u << 4
。尽管除了自文档化代码之外,这段代码当然毫无意义。 (当然,移动值 0 总是无害的。)
在 <<
的右操作数上使用 UINT8_C
是无稽之谈 - 该操作数不参与结果的任何类型提升。如果您需要使用无符号文字来满足编码标准,请使用 4u
。值得注意的是,在您实际上不需要无符号类型的情况下,像 MISRA-C 这样的标准 not 需要 u
后缀——这是工具误报的常见来源。
总结 - 使用这个:
pTxData[index] = 0u << 4;
此外,Klockwork 给出了错误的诊断信息。表达式中的运算符都可能等同于 unsigned char
而绝对不是工具所说的 signed char
。
1) 在 C99 中引入 7.18.4.1。
2) 参见
当被klocwork分析时,下面一行
pTxData[index] = ( UINT8_C(0) << UINT8_C(4) );
给出错误
Operand of bitwise operation has type 'signed char' instead of 'unsigned integer'
我已经通过删除任何 #define
将问题减少到最低限度,并且完全不知道为什么会发生这种情况。
在大多数表达式中,排名小于 int
的整数类型被转换为 int
(如果 int
可以无损失地表示所有值)或 unsigned int
(否则)。
为了简化一点,考虑等级对应于类型中的位数,位数越多,等级越高(对于术语的明确处理,请参阅语言参考(例如,您可能开始 here)).
这里似乎是这种情况,UINT8_C()
(可能是 unsigned char
伪装)返回的类型比 int
的级别小,所以你最终得到了一个签名类型。
现在,出现警告的原因是在所有情况下都没有很好地定义移位有符号整数类型。向左移动负值或在移动时溢出相当于 未定义的行为 ,这意味着如果遇到这两种情况中的任何一种,程序可能会以多种方式出现异常行为。 (在移动无符号类型时溢出是合法的,你会得到一个截断的值)。
此外,班次计数不能为负数。
但是,如果这是确切的代码,则警告是不必要的,因为显然将 0 向左移动 4 个位置是完全安全的。如果您使用变量而不是常量,编译器(或工具)将不会总是能够推断出这种转变的安全性,在这种情况下,您应该注意警告并以这样一种方式重写您的代码,即未定义的行为或警告。
对于那些不知道的人,UINT8_C
是一个 C 标准宏1) 用于获取 uint_least8_t
类型的整数常量而不是默认的 [=13] =].
因此 UINT8_C(0)
等同于 (uint_least8_t)0
。这将是一个小整数类型。因此,当作为左操作数传递给 <<
时,它会受到整数提升 2) 的影响。提升后它最终成为 int
类型,相当于只写 0
.
切勿将带符号的操作数与按位运算符一起使用,因此这是错误消息的核心原因。更正后的代码应类似于 0u << 4
。尽管除了自文档化代码之外,这段代码当然毫无意义。 (当然,移动值 0 总是无害的。)
在 <<
的右操作数上使用 UINT8_C
是无稽之谈 - 该操作数不参与结果的任何类型提升。如果您需要使用无符号文字来满足编码标准,请使用 4u
。值得注意的是,在您实际上不需要无符号类型的情况下,像 MISRA-C 这样的标准 not 需要 u
后缀——这是工具误报的常见来源。
总结 - 使用这个:
pTxData[index] = 0u << 4;
此外,Klockwork 给出了错误的诊断信息。表达式中的运算符都可能等同于 unsigned char
而绝对不是工具所说的 signed char
。
1) 在 C99 中引入 7.18.4.1。
2) 参见