通过klocwork分析时,以下行
pTxData[index] = ( UINT8_C(0) << UINT8_C(4) );
给出错误
按位运算的运算符的类型为“ signed char”,而不是 '无符号整数'
我已经通过删除任何#define
将问题减少到最低程度,并且完全不知道为什么会发生这种情况。
答案 0 :(得分: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之类的标准 not 不需要u
后缀-这是来自工具的误报的常见来源。
摘要-使用此:
pTxData[index] = 0u << 4;
此外,Klockwork提供了错误的诊断消息。表达式中的运算符都可能等效于unsigned char
,而且绝对不像该工具所说的signed char
。
1)在C99 7.18.4.1中引入。
答案 1 :(得分:1)
在大多数表达式中,等级小于int
的整数类型将转换为int
(如果int
可以代表所有值而不会丢失)或unsigned int
(否则)。
为简化起见,请考虑等级以与类型中的位数相对应,位数越多,等级越高(有关该术语的确定性处理,请参见语言参考(例如,您可以以{ {3}})。
在这里似乎是这样,UINT8_C()
返回的类型(可能是unsigned char
伪装而成)的等级要比int
小,因此最终得到带符号的类型。
现在,发出警告的原因是在所有情况下都没有很好地定义移位有符号整数类型。将负值左移或溢出,同时移位会导致未定义的行为,这意味着如果同时遇到这两种情况,程序可能会以多种方式发生错误行为。 (在转换无符号类型时溢出是合法的,您会得到一个截断的值)。
此外,班次计数不能为负。
但是,如果这是确切的代码,则无需发出警告,因为很明显,将0左移4位是完全安全的。如果使用变量而不是常量,则编译器(或工具)将无法总是推断出这种转换的安全性,在这种情况下,您应注意警告并以这样的方式重写代码:未定义的行为也不警告。