使用unsigned long类型进行位移会产生错误的结果

时间:2015-07-31 10:47:45

标签: c bit-shift unsigned

我有点困惑,因为我想在我的系统上初始化一个大小为8字节的unsigned long类型的变量(在我认为的每个现代系统上)。当我想将1 << 63分配给变量时,我得到了一个编译器警告但是数字实际为0.当我1 << 30时,我得到2 ^ 30 = 1073741824的预期结果。然而,当我1 << 31时,我得到2 ^ 64的结果(我认为;实际上这不应该是可能的),它打印18446744071562067968

有人可以向我解释这种行为吗?

4 个答案:

答案 0 :(得分:12)

1 << 63将在int算术中计算,而您的int可能是32位。

通过宣传其中一个论点来解决这个问题:1ULL << 63会做到这一点。

ULL表示表达式至少为64位。

答案 1 :(得分:2)

表达式1 << 63的类型为intint的范围是-2 31 ... 2 31 - 1在大多数系统上,2 63 对于那个来说太大了。尝试使用(unsigned long)1 << 631UL << 63unsigned long类型的值移至63位。

答案 2 :(得分:2)

此处1称为整数常量。根据标准中指定的规范,C11,第§6.4.4.1章的语法是

  

整数常数:
十进制常量整数后缀 opt
  八进制常量整数后缀 opt
十六进制常量   整数后缀<子>选择

关于语义学,

  

整数常量的类型是相应列表中可以表示其值的第一个。

并且表格显示,如果没有后缀,并且该值可在int范围内表示,则应将其视为int。因此,此处1被视为int,其通常 4个字节,或32位,在您的情况下也相同。

要明确指定1unsigned 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