使用 unsigned long 类型进行位移会产生错误的结果
bit shifting with unsigned long type produces wrong results
我有点困惑,因为我想在我的系统(我想是每个现代系统)上初始化一个大小为 8 字节的 unsigned long
类型的变量。当我想将 1 << 63
分配给变量时,我收到了编译器警告,并且该数字实际上是 0。当我执行 1 << 30
时,我得到了 2 ^ 30 = 1073741824
的预期结果。然而,当我执行 1 << 31
时,我得到 2 ^ 64
的结果(我认为;实际上这不应该是可能的)打印 18446744071562067968
。
任何人都可以向我解释这种行为吗?
1 << 63
将在 int
算法中计算,而您的 int
可能是 32 位。
通过提升其中一个参数来解决这个问题:1ULL << 63
会做到。
ULL
表示表达式至少为 64 位。
表达式 1 << 63
的类型为 int
。 int
的范围是 -231 … 231 - 在大多数系统上是 1,263 太大了。尝试 (unsigned long)1 << 63
或 1UL << 63
将类型 unsigned long
的值左移 63 位。
这里的1
,叫做整数常量。根据标准 C11
中指定的规范,第 §6.4.4.1
章的语法是
integer-constant:
decimal-constant integer-suffixopt
octal-constant integer-suffixopt
hexadecimal-constant
integer-suffixopt
关于语义,
The type of an integer constant is the first of the corresponding list in which its value can be represented.
和 table 表示,如果没有后缀,并且值在 int
范围内代表 table,则应将其视为 int
。因此,这里的 1
被认为是 int
,通常 4 个字节,或 32 位,在您的情况下也是如此。
要明确指定 1
为 unsigned long
(64) 位,我们可以使用后缀,例如
1UL << 63
应该可以解决您的问题。
请注意:unsigned long
不保证为 64 位。 unsigned long long
保证至少有64位。但是,只要您使用 unsigned long
是 64 位的平台,您应该没问题
我建议您使用 1ULL
,因为这将为您提供 32 位和 64 位架构上的 64 位无符号整数。
在 32 位架构上 unsigned long
(因此 UL
)只有 32 位长,无法解决问题。
1ULL << 63
我有点困惑,因为我想在我的系统(我想是每个现代系统)上初始化一个大小为 8 字节的 unsigned long
类型的变量。当我想将 1 << 63
分配给变量时,我收到了编译器警告,并且该数字实际上是 0。当我执行 1 << 30
时,我得到了 2 ^ 30 = 1073741824
的预期结果。然而,当我执行 1 << 31
时,我得到 2 ^ 64
的结果(我认为;实际上这不应该是可能的)打印 18446744071562067968
。
任何人都可以向我解释这种行为吗?
1 << 63
将在 int
算法中计算,而您的 int
可能是 32 位。
通过提升其中一个参数来解决这个问题:1ULL << 63
会做到。
ULL
表示表达式至少为 64 位。
表达式 1 << 63
的类型为 int
。 int
的范围是 -231 … 231 - 在大多数系统上是 1,263 太大了。尝试 (unsigned long)1 << 63
或 1UL << 63
将类型 unsigned long
的值左移 63 位。
这里的1
,叫做整数常量。根据标准 C11
中指定的规范,第 §6.4.4.1
章的语法是
integer-constant:
decimal-constant integer-suffixopt
octal-constant integer-suffixopt
hexadecimal-constant integer-suffixopt
关于语义,
The type of an integer constant is the first of the corresponding list in which its value can be represented.
和 table 表示,如果没有后缀,并且值在 int
范围内代表 table,则应将其视为 int
。因此,这里的 1
被认为是 int
,通常 4 个字节,或 32 位,在您的情况下也是如此。
要明确指定 1
为 unsigned long
(64) 位,我们可以使用后缀,例如
1UL << 63
应该可以解决您的问题。
请注意:unsigned long
不保证为 64 位。 unsigned long long
保证至少有64位。但是,只要您使用 unsigned long
是 64 位的平台,您应该没问题
我建议您使用 1ULL
,因为这将为您提供 32 位和 64 位架构上的 64 位无符号整数。
在 32 位架构上 unsigned long
(因此 UL
)只有 32 位长,无法解决问题。
1ULL << 63