此操作的 unsigned long int 是否正确?
Is unsigned long int correct for this operation?
这是我的代码:
#include <stdio.h>
int main(int argc, char *argv[]) {
unsigned long int x = 0;
// trying to make x = 2,147,483,648
x = 1 << 31;
printf("%lu", x);
}
它返回 x = 18446744071562067968。我读到 unsigned long int 应该达到 4,294,967,296,那么为什么我不能使用 1 << 32 来设置 x 等于 2,147,483,648?
如果您的系统有 32 位整数,1 << 31
会导致未定义的行为。文字 1
是一个带符号的整数。
您需要进行无符号班次而不是有符号班次:
x = 1UL << 31;
我添加了L
,这样代码即使在16位系统上仍然是正确的,这样做也无妨。
非正式地,将 1
移入符号位是未定义的。正式文本可以在C11标准的6.5.7/4部分找到:
The result of E1 << E2
is E1
left-shifted E2
bit positions; vacated bits are filled with zeros. [...] If E1
has a signed type and nonnegative value, and E1
× 2
E2
is representable in the result type, then that is the resulting value; otherwise, the behavior is undefined.
你的另一个问题 "why can't I use 1 << 32
" 也包含在同一句话中。 1UL << 32
呢?如果您的系统有 32 位 unsigned long
那么根据 6.5.7/3 这也是未定义的:
[...] If the value of the right operand is negative or is greater than or equal to the width of the promoted left operand, the behavior is undefined
但如果您的系统是 64 位 unsigned long
,它就可以工作。为避免在不同系统上编译时代码中断(此目标称为 代码可移植性),您可以编写 (uint64_t)1 << 32
(或 1ULL << 32
),这是有保证的上班。
这是我的代码:
#include <stdio.h>
int main(int argc, char *argv[]) {
unsigned long int x = 0;
// trying to make x = 2,147,483,648
x = 1 << 31;
printf("%lu", x);
}
它返回 x = 18446744071562067968。我读到 unsigned long int 应该达到 4,294,967,296,那么为什么我不能使用 1 << 32 来设置 x 等于 2,147,483,648?
1 << 31
会导致未定义的行为。文字 1
是一个带符号的整数。
您需要进行无符号班次而不是有符号班次:
x = 1UL << 31;
我添加了L
,这样代码即使在16位系统上仍然是正确的,这样做也无妨。
非正式地,将 1
移入符号位是未定义的。正式文本可以在C11标准的6.5.7/4部分找到:
The result of
E1 << E2
isE1
left-shiftedE2
bit positions; vacated bits are filled with zeros. [...] IfE1
has a signed type and nonnegative value, andE1
×2
E2
is representable in the result type, then that is the resulting value; otherwise, the behavior is undefined.
你的另一个问题 "why can't I use 1 << 32
" 也包含在同一句话中。 1UL << 32
呢?如果您的系统有 32 位 unsigned long
那么根据 6.5.7/3 这也是未定义的:
[...] If the value of the right operand is negative or is greater than or equal to the width of the promoted left operand, the behavior is undefined
但如果您的系统是 64 位 unsigned long
,它就可以工作。为避免在不同系统上编译时代码中断(此目标称为 代码可移植性),您可以编写 (uint64_t)1 << 32
(或 1ULL << 32
),这是有保证的上班。