我有点困惑,因为我想在我的系统上初始化一个大小为8字节的unsigned long
类型的变量(在我认为的每个现代系统上)。当我想将1 << 63
分配给变量时,我得到了一个编译器警告但是数字实际为0.当我1 << 30
时,我得到2 ^ 30 = 1073741824
的预期结果。然而,当我1 << 31
时,我得到2 ^ 64
的结果(我认为;实际上这不应该是可能的),它打印18446744071562067968
。
有人可以向我解释这种行为吗?
答案 0 :(得分:12)
1 << 63
将在int
算术中计算,而您的int
可能是32位。
通过宣传其中一个论点来解决这个问题:1ULL << 63
会做到这一点。
ULL
表示表达式至少为64位。
答案 1 :(得分:2)
表达式1 << 63
的类型为int
。 int
的范围是-2 31 ... 2 31 - 1在大多数系统上,2 63 对于那个来说太大了。尝试使用(unsigned long)1 << 63
或1UL << 63
将unsigned long
类型的值移至63位。
答案 2 :(得分:2)
此处1
称为整数常量。根据标准中指定的规范,C11
,第§6.4.4.1
章的语法是
整数常数:
十进制常量整数后缀 opt
八进制常量整数后缀 opt
十六进制常量 整数后缀<子>选择子>
关于语义学,
整数常量的类型是相应列表中可以表示其值的第一个。
并且表格显示,如果没有后缀,并且该值可在int
范围内表示,则应将其视为int
。因此,此处1
被视为int
,其通常 4个字节,或32位,在您的情况下也相同。
要明确指定1
为unsigned long
(64)位,我们可以使用后缀,例如
1UL << 63
应解决您的问题。
请注意:unsigned long
不保证为64位。 unsigned long long
保证至少有64位。但是,只要您使用unsigned long
为64位的平台,就可以了。
答案 3 :(得分:2)
我建议您使用1ULL
,因为这样可以在32位和64位架构上为您提供64位无符号整数。
32位架构unsigned long
(以及UL
)只有32位长,无法解决问题。
1ULL << 63