解决复合赋值中的转换警告

时间:2013-09-05 07:00:57

标签: c type-conversion warnings implicit-conversion

在我的代码中,我有很多variable <<= 1;个句子,其中variable的类型为uint16_t。编译器吐出警告说

  

从'int'转换为'uint16_t'可能会改变其值[-Wconversion]

我该如何解决?我可以使用像variable = (uint16_t)(variable << 1)这样的长格式符号 - 但我想保留简短的符号。

2 个答案:

答案 0 :(得分:5)

根据我对标准的阅读,你不能因为这个原因而放弃这个警告:

uint16_t foo;
foo <<= 1;

相当于

uint16_t foo;
foo = foo << 1;

然而,这被卷入“整数推广”的世界。

foo << 1”表达式的值类型为“foo”,但是在左移之前,它必须先进行“整数提升”; C99标准的 6.3.1.1.2 部分指定:“如果int可以表示原始类型的所有值,则该值将转换为int。”

这使得代码的非隐式版本(带有额外的括号)如下:

uint16_t foo;
foo = ((int)foo) << 1;

如果警告您使用的是32位或64位整数的系统(或任何大于16位的系统),那么您确实将较大的值推向较小的值。

解决这个问题的一种方法是明确表达你的演员表:

uint16_t foo;
foo = (uint16_t)(foo << 1);

但这意味着不,你不能使用较短的按位移位赋值运算符。

如果你真的这么做,请考虑制作一个帮助函数,使你的代码清晰,编译干净。

void LS(uint16_t &value, int shift) {  // LS means LeftShift
  *value = (uint16_t)(*value << shift);
}

LS(&foo, 1);

TL; DR:不,您不能使用短操作符并同时避免该警告。

答案 1 :(得分:1)

您收到警告,因为variable <<= 1;相当于:

variable = variable << 1;

由于默认的整数提升,右侧的类型为int,而非uint16_t。解决此问题的最佳方法是不要使用小于int类型。