3

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

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

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

4

2 回答 2

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:不,您不能同时使用短运算符并避免该警告。

于 2013-09-05T07:34:34.507 回答
1

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

variable = variable << 1;

由于默认整数促销,右侧有 type int,而不是。uint16_t解决这个问题的最好方法是不要使用小于int类型。

于 2013-09-05T07:23:02.347 回答