如何修复由-Wconversion引起的错误?

如何修复由-Wconversion引起的错误?,c,gcc,C,Gcc,我有一段假代码/示例代码: #包括 uint8_t函数(uint16_t val0、uint16_t val1、uint16_t val2) { uint8_t r; val0+=0x7F; val1+=(uint16_t)0x7F; val2+=0x7FU; r=(uint8_t)((val0+val1+val2)>>8); r这个问题说明了为什么-Wconversion过于热心以至于基本上没有用 在C语言中,没有小于int的算术运算。例如: val0 += 0x7F; 被评估为 val0

我有一段假代码/示例代码:

#包括
uint8_t函数(uint16_t val0、uint16_t val1、uint16_t val2)
{
uint8_t r;
val0+=0x7F;
val1+=(uint16_t)0x7F;
val2+=0x7FU;
r=(uint8_t)((val0+val1+val2)>>8);

r这个问题说明了为什么
-Wconversion
过于热心以至于基本上没有用

在C语言中,没有小于
int
的算术运算。例如:

val0 += 0x7F;
被评估为

val0 = (int)val0 + 0x7F;
不使用强制转换将赋值返回到
val0
,然后触发
-Wconversion
。从某种意义上说,这是一个合理的警告:
+
运算符不会溢出,但将结果返回可能会丢失部分结果,编译器会告诉您这一点(尽管有些尴尬)

如果要使用
-Wconversion
,基本上不能将复合赋值运算符(如
+=
)用于小于-
int
的类型。您需要写出等价的表单,并使用强制转换来指示要进行有损转换。例如,在这里您可以编写:

val0 = (uint16_t)(val0 + 0x7F);

我不认为这是一种非常好的风格,但一些编码标准/策略(例如,我认为,MISRA)强制要求它。

强制转换/位掩码可以做到这一点

例如:

#包括
uint8_t函数(uint16_t val0、uint16_t val1、uint16_t val2)
{
无符号整数r;
val0=(uint16_t)(val0+0x7Fu);
/*val0=(val0+0x7Fu)&0xFFFF*/
val1=(val1+0x7Fu)&0xFFFF;
val2=(val2+0x7FU)&0xFFFF;
r=((0u+val0+val1+val2)>>8);

r=(r升级编译器版本如果可能的话,
-Wconversion
的早期版本会产生一些像这样可怕的误报,而且它比以前稍微好一些time@M.M我使用gcc 9.2.1OK,似乎他们还有一些改进的空间+1“尝试并避免短于int的类型可能是个好主意”。即使没有
-Wconversion
,这也是正确的。使用此类类型几乎总是一个错误,尤其是对于参数/局部变量。它们主要用于数组或结构中的大容量存储,其中
int
或更大的值将消耗更多的空间。
val0 = (int)val0 + 0x7F;
val0 = (uint16_t)(val0 + 0x7F);
#include <stdint.h>

uint8_t func(uint16_t val0, uint16_t val1, uint16_t val2)
{
    unsigned int r;
    val0 = (uint16_t)(val0 + 0x7Fu);
    /*val0 = (val0 + 0x7Fu) & 0xFFFF;*/
    val1 = (val1 + 0x7Fu) & 0xFFFF;
    val2 = (val2+0x7FU) & 0xFFFF;
    r = ((0u+val0+val1+val2) >> 8);
    r = ( r << (uint8_t)(val2 & 0x3u)) & 0xFF;
    return r&0xFF;
}