【问题标题】:-Wconversion warning while using operator <<= on unsigned char-Wconversion 警告,同时在无符号字符上使用运算符 <<=
【发布时间】:2015-06-30 01:07:31
【问题描述】:

当我用 gcc 编译以下代码时:

int main()
{
  unsigned char c = 1;
  c <<= 1;  // WARNING ON THIS LINE
  return 0;
}

我收到此警告:

conversion to ‘unsigned char’ from ‘int’ may alter its value [-Wconversion]

为什么?这段代码有什么问题?实际上,我真的可以在 unsigned char 变量上使用运算符 &lt;&lt;= 吗?

编译命令:

g++ test.cpp -Wconversion -o test.exe

【问题讨论】:

  • 在我看来,对于编译器编写者和用户来说,这都是“该死,如果你不这样做”的情况之一。作为用户,您所写的内容是干净的,并且产生了预期的答案,并且通常完全没有例外。它不需要额外的语言混乱来使其更难理解。作为编译器编写者,技术上存在缩小转换,因此警告在技术上是正确的。但我不禁觉得,在这种情况下,或者涉及short的类似情况(估计也触发了警告),警告真的没有建设性。

标签: c++ gcc bitwise-operators unsigned-char


【解决方案1】:

这是一个有效的警告:

c <<= 1;

相当于:

c = c << 1

&lt;&lt; 的规则说操作数被提升,在这种情况下将提升为int,结果是提升类型。所以最后会有从intunsigned char 的转换,这可能会导致值改变。

代码有效,警告告诉您正在进行隐式转换,在某些情况下,转换可能会改变值。使用演员表将使警告静音。隐式转换的结果可能非常违反直觉,并且在某些情况下是未定义的行为。请参阅gcc Wconversion wiki for some details

如果不手动扩展操作并使用static_cast,我看不到删除警告的方法:

c = static_cast<unsigned char>( c << 1 );

正如我们从gcc bug report 的长线程中看到的那样,并不是每个人都认为这是这个警告的有用案例。

参考draft C++ standard 部分5.8 移位运算符:

操作数应为整数或非范围枚举类型,并执行整数提升。结果的类型是提升的左操作数的类型 [...]

以及来自5.17 部分的赋值和复合赋值运算符:

E1 op = E2 形式的表达式的行为等价于 E1 = E1 op E2,除了 E1 只评估一次。 [...]

【讨论】:

  • 如果做c &lt;&lt;= static_cast&lt;unsigned char&gt;(1);,我也有问题。您是说 C++ 中没有 1 字节类型的移位运算符吗? :-/
  • 请参阅Why must a short be converted to an int before arithmetic operations in C and C++?,了解为什么将操作数提升为更广泛的类型。主要是因为它可以更快地生成代码。
  • 它似乎终于被接受为一个错误,现在它已在 gcc 10.0 中修复
猜你喜欢
  • 2021-11-06
  • 2023-03-18
  • 1970-01-01
  • 2022-08-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-01-05
相关资源
最近更新 更多