【发布时间】:2017-03-28 15:51:27
【问题描述】:
我在做一些按位练习时遇到了这个不寻常的错误。当pow() 的输出被强制转换为unsigned int 时,pow() 以变量 作为指数调用的结果变为零,而指数为文字时的结果整数 被强制通常 为 0xFFFFFFFF (2^32 - 1)。这只发生在值过大时,在本例中为 2^32。用作指数参数的变量类型似乎不会影响此结果。我还尝试将pow() 的两个调用的输出存储为双精度,然后在引用变量时应用强制;差距依然存在。
#import <math.h>
int main (void) {
int thirtytwo = 32; // double, unsigned, etc... all yielded the same result
printf("Raw Doubles Equal: %s\n", pow(2, 32) == pow(2, thirtytwo) ? "true" : "false"); // -> true
printf("Coerced to Unsigned Equal: %s\n", (unsigned) pow(2, 32) == (unsigned) pow(2, thirtytwo) ? "true": "false"); // -> false
return 0;
}
出于好奇,我通过 clang/llvm 运行了相同的代码,得到了不同的结果:无论指数是否为变量,将结果强制为 unsigned int 都会产生零(如预期的那样)。
编辑:最大 32 位无符号整数是 2^32 - 1,因此这两种强制输出实际上都正确。我的错误是溢出了整数大小限制。为什么 gcc 本质上向下舍入到最大整数值是一个有趣的好奇心,但并不是特别重要。
【问题讨论】:
-
如果无符号整数是 32 位长,你怎么认为它们代表 2^32?也许通过点亮不存在的第 33 位?你溢出一个无符号整数,得到 0。
-
这并不能解释不一致之处。当指数是文字整数时不会发生溢出,例如
(unsigned) pow(2, 32) == 0xFFFFFFFF. -
对于一个
0xFFFFFFFF == 2^32 -1,而不是2^32。当您使用常量而不是变量进行调用时,编译器可以随意优化。不同的编译器甚至可能做不同的事情。 -
要获得 2 的幂,请改用
1 << exp