考虑这个程序:
int main(void) { short x = 1; x = x+x; return 0; }
使用-Wconversion编译生成
nonsense.c: In function 'main': nonsense.c:3:8: warning: conversion to 'short int' from 'int' may alter its value [-Wconversion]
这是公平的在大多数平台上,如果发生这种情况,那么这可能会导致x == 0x8000. (你得到这个警告的实际机制:操作数受“通用算术转换”的限制,将它们扩展为int;因此结果也是int类型;然后分配给x是一个隐式转换更宽更窄的类型.)但是,假设你期望并打算这种行为. (您正在模拟16位处理器或16位移位寄存器;或者您知道此代码中x的可能值的范围,它将永远不会溢出.)您可以通过放入一个明确的方式来告诉编译器投:
int main(void) { short x = 1; x = (short)(x+x); return 0; }
然后不会抱怨.
到现在为止还挺好.但是,如果引起麻烦的作业是复合赋值 – =,* =,<< =等等 - 那么就我看到没有办法摆脱这个警告,因为没有'你可以插入显式转换的代码中的任何一点. 这意味着,例如,你不能拥有全部
> -Wconversion在你的项目的顶级编译器标志,以捕获所有真正的错误,它的意图.
>复合赋值运算符代码中的任何一个实例应用于比int短的整数类型.
>无警告的构建.
这似乎很伤心.
所以,问题是:有没有办法解决这个问题?我可以看到以下几种方法:
>使用#pragma GCC诊断…可以禁止使用已知会引发它的代码中的警告,尽管没有错误. (下载:丑,编译器特定)
>将复合赋值展开为更长的单个作业并插入显式转换. (下行:超丑)
>关闭 – 转换. (下降:此警告在别处有用.)
>提出警告. (不利于使用-Werror;在任何情况下,优良做法是使您的代码编译完全没有任何警告,因为“无警告”和“某些警告”之间的区别比“某些警告“和”更多的警告“).
所有这些似乎都不能令人满意,我想知道是否有一些聪明的人,我失踪了.
(注:当然我会接受一个“不,就是这样”的答案,如果这其实是真相.)
所以,看起来好像答案是真的是预期的行为,没有办法阻止它比上面列出的更好. (Mark B观察到您可以编写一个与=但是使用显式转换相同的函数.ecatmur建议使用operator =函数定义一个新类型来进行显式转换.)
我接受马克B的答案标题中的问题的实际答案只是“是”:-).