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