gcc的-Wconversion是否与使用短于int的整数类型的复合赋值(+ =等)不兼容?

Gar*_*han 11 c c++ gcc warnings casting

gcc有一个有用的标志-Wconversion,当存在从较宽类型到较窄类型的隐式转换时会产生警告,可能会丢失信息.不幸的是,它有以下......无益......行为.


考虑这个程序:

int main(void) {
  short x = 1;
  x = x+x;
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

用-Wconversion编译它会产生

nonsense.c: In function 'main':
nonsense.c:3:8: warning: conversion to 'short int' from 'int' may alter its value [-Wconversion]
Run Code Online (Sandbox Code Playgroud)

这是公平的; 在大多数平台上,如果发生这种情况,你会做一些你可能没想到的事情x==0x8000.(获得此警告的实际机制:操作数+受"通常的算术转换"的影响,将它们扩展为int;因此结果也是int类型;然后分配回来x是从更广泛的隐式转换到较窄的类型.)但是假设你确实期望并打算这种行为.(您正在模拟一个16位处理器,或一个16位移位寄存器;或者您知道x此代码中可能值的范围,它永远不会溢出.)您可以通过输入显式转换来告诉编译器:

int main(void) {
  short x = 1;
  x = (short)(x+x);
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

然后它不会抱怨.


到现在为止还挺好.但是,如果这是造成麻烦的分配是一个复合赋值- ,,+= 等-那么,只要我可以看到有没有办法摆脱这种警告,因为没有代码中的任何点在哪你可以插入显式的演员表.*=<<=

这意味着,例如,你不能拥有所有

  • -Wconversion项目的顶级编译器标志,以捕获它的所有真正错误.
  • 复合赋值运算符代码中任何位置的任何实例都应用于短于的整数类型int.
  • 无警告构建.

这似乎很难过.


所以,问题:有一个解决这个问题的好方法吗?我可以看到以下方式:

  • 使用#pragma GCC diagnostic ...禁用于已知会招惹它尽管没有错误的代码位的警告.(下行:丑陋,特定于编译器.)
  • 将复合赋值扩展为更长的单个赋值并插入显式强制转换.(下行:非常丑陋.)
  • 关闭-Wconversion.(下行:此警告在其他地方很有用.)
  • 忍受警告.(下行方面:与使用不兼容-Werror;在任何情况下,最好不要在没有任何警告的情况下编译代码,因为"无警告"和"某些警告"之间的差异比"某些警告"之间的差异更容易发现"更多警告".)

所有这些似乎都不尽如人意,我想知道是否有一些我更缺失的东西.

(注意:当然,如果真的是真相,我会接受"不,那就是"答案.)


因此,看起来好像答案是这确实是预期的行为,并且没有办法阻止它比上面列出的更好.(Mark B观察到你可以编写一个+=与显式转换相同的函数.ecatmur建议定义一个带有operator+=函数的新类型来进行显式转换.)

我接受了Mark B的回答; 标题中问题的实际答案只是"是":-).

Mar*_*k B 1

我假设在这种情况下警告的逻辑是它在功能上与复合运算符实现的操作相同。复合运算符语法应该执行非常明显的复合操作,在这种情况下,您想明确表示您确切地知道自己在做什么。当你想清楚地表明意图的存在时,更明确地拼写出代码总是会获胜:你只编写一次,但更长的拼写版本将使未来的维护者完全清楚你的意图是什么。

我建议只对操作进行分解并阐明演员阵容。你的维护者真的不会介意,而且我怀疑他们会认为这很丑。

或者,创建一个scalar_mult(short&, short)函数来隐藏强制转换。然后你表现出明确的意图避免在每个表达式中进行强制转换。

最后,您也许可以完全避免使用较短的类型,从而避免出现警告。