2

用 klocwork 分析时,下面这行

pTxData[index] =  ( UINT8_C(0) << UINT8_C(4) );

给出错误

按位运算的操作数类型为“有符号字符”而不是“无符号整数”

我已经通过删除任何问题将问题减少到最低限度,#define并且完全不知道为什么会发生这种情况。

4

2 回答 2

5

对于那些不知道的人,UINT8_C是一个 C 标准宏1)用于获取类型的整数常量uint_least8_t而不是默认的int.

因此UINT8_C(0)等价于(uint_least8_t)0。这将是一个小整数类型。因此,当作为左操作数传递给 时,它会受到整数提升2)<<的影响。提升后它最终成为类型int,相当于只是写作0

您永远不应该将带符号的操作数与按位运算符一起使用,因此这是错误消息的核心原因。更正后的代码应如下所示0u << 4。尽管除了自记录代码之外,这段代码当然对任何东西都毫无意义。(当然,将值 0 移动总是无害的。)

UINT8_C在右边的操作数上使用<<是无稽之谈 - 该操作数不参与结果的任何类型提升。如果您需要使用无符号文字来满足编码标准,请使用4u. 值得注意的是,在您实际上不需要无符号类型的情况下,像 MISRA-C 这样的标准不需要u后缀——这是工具误报的常见来源。

摘要 - 使用这个:

pTxData[index] =  0u << 4;

此外,Klockwork 给出了不正确的诊断信息。您表达式中的运算符既可能等同于该工具所说的,unsigned char也绝对signed char不像该工具所说的那样。


1)在 C99 7.18.4.1中引入。

2)隐式类型提升规则

于 2019-02-27T11:38:27.213 回答
1

在大多数表达式中,等级小于intget 的整数类型转换为int(如果int可以无损失地表示所有值)或unsigned int(否则)。

为了简化一点,请考虑将等级与类型中的位数相对应,位数越多,等级越高(有关该术语的明确处理,请参阅语言参考(例如,您可以从这里开始))。

这里似乎是这种情况,由UINT8_C()(可能unsigned char是伪装的)返回的类型的等级小于int,所以你最终有一个带符号的类型。

现在,警告的原因是在所有情况下都没有很好地定义转换有符号整数类型。向左移动负值或在移动时溢出相当于未定义的行为,这意味着如果遇到这两个条件中的任何一个,程序可能会以多种方式出现异常。(转移无符号类型时溢出是合法的,你会得到一个截断的值)。

此外,班次计数不能为负数。

但是,如果这是确切的代码,则警告是不必要的,因为显然将 0 左移 4 个位置是完全安全的。如果您使用变量而不是常量,编译器(或工具)并不总是能够推断出这种转变的安全性,在这种情况下,您应该注意警告并以这样的方式重写您的代码未定义的行为或警告。

于 2019-02-27T10:55:08.570 回答