【发布时间】:2015-04-07 04:57:39
【问题描述】:
我正在编写一个非常基本的程序来打印 C 语言中 unsigned long long 变量的范围(0 到 ((2 ^ n) - 1),其中 n 是任何系统中的数据类型(其中安装了 C 并根据编译器)。在我的系统中,long long 变量的大小为 8 个字节。
我正在使用以下代码:
#include<stdio.h>
#include<math.h>
int main()
{
unsigned long long n;
//n = pow(2, 63);
//n = (n * 2) - 1;
n = pow(2, 64) - 1;
printf("\nn: %llu\n", n);
return 0;
}
在编译时,gcc 给了我以下错误:
Print_long_long_int.c:10:2:警告:隐式常量转换溢出 [-Woverflow]。
在执行它时,我得到了正确的输出 号码:18446744073709551615
但是,如果我从行中删除单个 cmets 并使用它们:
n = pow(2, 63);
n = (n * 2) - 1;
代替:
n = pow(2, 64) - 1;
它没有给我任何这样的警告。并正常执行。 为什么会出现这种差异?
谢谢!
【问题讨论】:
-
这可能意味着 GCC 没有在运行时调用
pow(),而是在编译时评估常量,它注意到pow(2, 64)太大而无法放入 64 位无符号整数,但是并没有拒绝完成编译,并且确实通过一些或多或少的迂回手段得到了正确的答案。其他编译器或优化较少的 GCC 可能会做不同的事情。 -
pow根本不是该任务的正确工具,它适用于double而不适用于整数类型。所以在任何时候你都可能失去精度。使用移位运算符<<获得2的大幂。但即便如此,如果您的类型只有 64 位,您显然无法获得高于 63 的功率。