C 隐式强制转换后溢出

C 隐式强制转换后溢出,c,casting,double,integer-overflow,C,Casting,Double,Integer Overflow,当我尝试从double到unsigned long进行隐式转换时,有一个溢出警告:“警告:隐式常量转换中溢出[-Woverflow]” 以下是说明: unsigned long ulongMax = pow(2.0, 64.0) - 1; 但当我像下面这样显式地抛出它时,它是好的 unsigned long ulongMax = (unsigned long) (pow(2.0, 64.0) - 1); 我不明白为什么我有一个警告,结果(18446744073709551615)与标题“l

当我尝试从double到unsigned 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
相同。

警告意味着如果
pow(2.0,64.0)-1
太大或带有小数部分(比如1.7*10^308,这是双打的最大值)或0.9,将被截断为0)


当使用显式cast
(unsigned long)(pow(2.0,64.0)-1)时,您没有得到警告的原因是,显式地说“我实际上想从这个双精度中得到一个unsigned long(不管它有多么糟糕的后果)”

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

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

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

显式强制转换消除了警告,因为它本质上告诉编译器您知道正在发生的事情,并且希望它保持安静并按您所说的去做。

pow(2.0,64.0)
返回一个
双精度

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

现在,从浮点型到整数型的范围外强制转换会导致错误,无需诊断


在第一种情况下,您的编译器试图通过警告您这种未定义的行为来提供帮助,但是(大概)它将添加强制转换视为您发出的一条消息,表示“我不想听到此警告”。

您的问题应该包括确切的警告消息,最好确认ulong的大小,例如
printf(“%lu\n”,ULONG_MAX);
我已经包含了警告消息。在我的系统(Arch linux 64位)上,正如我所说,ULONG_MAX的值是18446744073709551615。在我看来,double表示为int,但你是对的。因此,double中整数的最大值应该是2^52-1。谢谢。