警告:隐式常量转换溢出
在下面的程序中,第 5 行确实按照预期给出了溢出警告,但令人惊讶的是,第 4 行在 GCC 中没有给出任何警告:http://www.ideone.com/U0BXn
int main()
{
int i = 256;
char c1 = i; //line 4
char c2 = 256; //line 5
return 0;
}
我认为这两行都应该给出溢出警告。或者我缺少什么?
引导我做这个实验的主题是: typedef 类型检查?
我说了以下内容(我从答案中删除了它,因为当我运行它时,它没有按我的预期显示):
//However, you'll get warning for this case:
typedef int T1;
typedef char T2;
T1 x = 256;
T2 y = x; //possible overflow warning! (but it doesn't give warning :()
In the following program, the line 5 does give overflow warning as expected, but surprisingly the line 4 doesn't give any warning in GCC: http://www.ideone.com/U0BXn
int main()
{
int i = 256;
char c1 = i; //line 4
char c2 = 256; //line 5
return 0;
}
I was thinking both lines should give overflow warning. Or is there something I'm missing?
The topic which led me to do this experiment is this: typedef type checking?
There I said the following(which I deleted from my answer, because when I run it, it didn't show up as I had expected):
//However, you'll get warning for this case:
typedef int T1;
typedef char T2;
T1 x = 256;
T2 y = x; //possible overflow warning! (but it doesn't give warning :()
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
-Wall
不包含很多选项。-Wconversion
是其中之一,它会警告您感兴趣的行为。请参阅 http://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html
-Wall
doesn't include many options.-Wconversion
is one of them and warns about the behavior you're interested in.See http://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html
在将
int
值赋给char
对象的一般情况下,编译器不知道int
是否超出了范围。字符
。更仔细地查看实际警告:
正是在这种特定情况下,编译器能够向您发出警告,其中常量被转换为
char
。同样,如果您将i
的声明更改为const
:您也会收到警告,因为分配给
c2
的值是常数表达式。另请注意,该警告有些误导,因为转换在技术上并没有“溢出”。算术溢出会在 C++ 中产生未定义的行为。缩小转换(如将
int
转换为char
,如果int
的范围大于char
)会产生一些实现 -定义的转换。In the general case of assigning an
int
value to achar
object, the compiler doesn't know whether theint
is out of range of thechar
.Look at the actual warning more closely:
It is in this specific case, where a constant is being converted to
char
that the compiler is able to warn you. Likewise, if you changed the declaration ofi
to beconst
:you will also get the warning, because the value being assigned to
c2
is a constant expression.Note also that the warning is somewhat misleading as the conversion does not technically "overflow." Arithmetic overflow yields undefined behavior in C++. A narrowing conversion (like
int
tochar
, ifint
has a larger range thanchar
) yields some implementation-defined conversion.嗯,第 5 行是一个任何编译器都可以直接看到的明显错误,并且始终是一个错误。第 4 行至少需要一些数据流分析才能发现错误。也许这不是通过站点使用的设置来完成的,或者编译器编写者可能没有认为这一点足够重要而无法弄清楚。
Well, line 5 is an obvious error that any compiler can see directly, and always an error. Line 4 would require at least some data flow analysis to discover the error. Perhaps this isn't done with the settings used at the site, or perhaps the compiler writers didn't consider this important enough to figure it out.
GCC 4.3 后,
-Wconversion
的语义已更新,以检测可能更改值的隐式转换,但您还必须启用-Wsign-conversion
,因为否则由于有符号和无符号类型之间的强制转换,您不会收到可能更改数字符号的代码的警告。与 Crazy Eddie 所说的相反,在 GCC 4.3(当时尚未发布)之前,
-Wconversion
并没有普遍检查由隐式类型转换等引入的问题。相反,它检查您的程序的行为是否与使用旧式 K&R 函数原型时的行为不同。这不仅意味着它没有对所有隐式类型转换/强制问题发出警告,而且还意味着一些好的代码给出了不必要的警告。当然,使用
g++
不会出现任何错误,因为这样的原型无论如何都不是有效的 C++。Post GCC 4.3, the semantics of
-Wconversion
have been updated to detect implicit conversions that might change a value, but you have to enable-Wsign-conversion
as well, because otherwise you won't get a warning for code that might change the sign of a number due to coercion between signed and unsigned types.Contrary to what Crazy Eddie is saying, prior to GCC 4.3 (which hadn't been released yet at the time)
-Wconversion
didn't generically check for problems introduced by implicit type conversion and the like. Rather, it checked whether your program would behave differently than it would have behaved if it had used old-style K&R function prototypes.This not only meant that it didn't give a warning on all implicit type conversion / coercion problems, but it also meant that some good code gave an unnecessary warning. And of course, you'd get no error with
g++
because such prototypes aren't valid C++ anyway.