隐式转换后溢出

时间:2015-11-26 23:33:22

标签: c casting double integer-overflow

当我尝试从double到无符号long进行隐式转换时,我有一个溢出警告:"警告:隐式常量转换溢出[-Woverflow]"。

以下是指示:

unsigned long ulongMax = pow(2.0, 64.0) - 1; 

但是当我明确表达如下所示时,它没问题!

unsigned long ulongMax = (unsigned long) (pow(2.0, 64.0) - 1);

我不明白为什么会收到警告,结果(18446744073709551615)与标题" limits.h"中的ULONG_MAX相同。

3 个答案:

答案 0 :(得分:3)

pow(2.0, 64.0)返回double

但是(假设IEEE754系统正常),值pow(2.0, 64.0)pow(2.0, 64.0) - 1实际上是相等的。这是因为我们超出了double中相邻整数完全具有代表性的范围。 (当然,64位双精度不能代表所有64位整数。)

现在,从浮点到整数类型的超出范围的转换导致undefined behaviour,无需诊断。

你的编译器试图通过在第一种情况下警告你这个未定义的行为来提供帮助,但是(大概)它会将演员的添加视为你说的消息"我不想要听到这个警告"。

答案 1 :(得分:2)

警告意味着如果pow(2.0, 64.0) - 1太大或者小数部分(例如1.7 * 10 ^ 308,这是双打的最大值)或0.9,它可能会失去精度,这将被截断为0)

使用显式强制转换(unsigned long) (pow(2.0, 64.0) - 1)时没有收到警告的原因是明确表示“我实际上想要从这个双重中获得无符号长度(无论其令人讨厌的后果)”

答案 2 :(得分:2)

您收到警告的最可能原因是您平台上的unsigned long大小为32位,而不是64位。

如果切换到64位无符号,则警告将消失:

unsigned long long ulongMax = pow(2.0, 64.0) - 1; 
printf("%llu", ulongMax);

Demo.

显式强制转换消除了警告,因为它本质上告诉编译器你知道发生了什么,并且你希望它保持安静并像你说的那样。