为什么我不能在64位计算机上将2 ^ 64存储在unsigned long中?

时间:2018-05-16 17:59:10

标签: c binary integer x86-64 unsigned

我错过了什么吗?我运行了以下内容:

$ uname -a
Linux archlinux 4.16.6-1-ARCH #1 SMP PREEMPT Mon Apr 30 12:30:03 UTC 2018 x86_64 GNU/Linux

然后在C程序中:

long l;
printf("sizeof long: %d\n", sizeof l);

输出:

sizeof long: 8

这不意味着每个long包含64位吗? 但是当我执行以下代码行时:

printf("2^64: %ld\n",  1UL<<64);

我从gcc收到以下警告:

  

sizeof.c:14:29:警告:左移计数&gt; =类型宽度[-Wshift-count-overflow]

如果我将左移位减少到63,则警告消失,但输出:

  

2 ^ 64:-9223372036854775808

这让我相信我的无符号长度为64个可用位的假设是不正确的,但为什么呢?

2 个答案:

答案 0 :(得分:9)

数字2 ^ 64要求65位正确表示二进制 - 位#65设置,其余为零。

这与无符号8位数字最多只能达到255(2 ^ 8 - 1)的原因相同,无符号16位数字最多只能达到65535(2 ^ 16 - 1),依此类推

答案 1 :(得分:2)

sizeof确实会返回字节数,所以是的,它确实有64位。 使用N二进制数字,您可以表示总共2^N个数字。如果您的变量是无符号的,则表示[0, (2^N)-1]范围。如果它是签名号码,则范围应为[-2^(N-1), +2^(N-1)-1]。如果您想了解有关已签名整数的更多信息,可以阅读&#34; Two&#39;补码&#34;。

继续显示整数:告诉printf如何解释变量。如果你告诉它有符号整数,那么它将使用最高有效位作为符号而不是值2^63(再次检查两个补码)。

另一方面,这将打印整数unsigned:

printf("%lu", x);