C 中的左移运算符给出奇怪的结果
Left shift operator in C giving strange result
我有以下程序:
int main()
{
int64_t a = 241294423792285589;
printf("a = %lld, a << 63 = %lld", a, a << 63);
return 0;
}
我原以为 a << 63
为 0,但它打印出来:
a = 241294423792285589, a << 63 = -9223372036854775808
这是为什么?
如果将这些整数转换为带符号的 2 的二进制补码,您就会明白原因:
241294423792285589 二进制是
0000001101011001010000000000000000000000011010111111011110010101
将其左移 63 个点将导致 right-most 1
以 left-most 二进制数字结束:
1000000000000000000000000000000000000000000000000000000000000000
其中2的补码二进制是-9223372036854775808.
您可以在线找到二进制 <-> 十进制转换器(例如这个:https://www.rapidtables.com/convert/number/decimal-to-binary.html),这有助于使这一点更清楚。
或者您甚至可以试试这个移位计算器:https://bit-calculator.com/bit-shift-calculator
您的移位表达式有未定义的行为。您无法从这种转变中有意义地期待任何价值。
在 6.5.7/4
中描述了带符号 E1
左移 E1 << E2
的 C 行为
If E1 has a signed type and nonnegative value, and E1 × 2E2 is representable in the result type, then that is the resulting value; otherwise, the behavior is undefined.
问题是您在 64 位字中将奇数(设置了最低有效位的数字)左移 63 位。您获得的值为
0b1000_0000_0000_0000_...._0000
或
0x8000000000000000
那个(二进制补码)是你在问题中 post 的数字。
无论如何,将带符号的 64 位数字 移动 63 位是未定义的行为,因此这意味着您可以收到任何东西......如果是巨大的负数。
我有以下程序:
int main()
{
int64_t a = 241294423792285589;
printf("a = %lld, a << 63 = %lld", a, a << 63);
return 0;
}
我原以为 a << 63
为 0,但它打印出来:
a = 241294423792285589, a << 63 = -9223372036854775808
这是为什么?
如果将这些整数转换为带符号的 2 的二进制补码,您就会明白原因:
241294423792285589 二进制是
0000001101011001010000000000000000000000011010111111011110010101
将其左移 63 个点将导致 right-most 1
以 left-most 二进制数字结束:
1000000000000000000000000000000000000000000000000000000000000000
其中2的补码二进制是-9223372036854775808.
您可以在线找到二进制 <-> 十进制转换器(例如这个:https://www.rapidtables.com/convert/number/decimal-to-binary.html),这有助于使这一点更清楚。
或者您甚至可以试试这个移位计算器:https://bit-calculator.com/bit-shift-calculator
您的移位表达式有未定义的行为。您无法从这种转变中有意义地期待任何价值。
在 6.5.7/4
中描述了带符号E1
左移 E1 << E2
的 C 行为
If E1 has a signed type and nonnegative value, and E1 × 2E2 is representable in the result type, then that is the resulting value; otherwise, the behavior is undefined.
问题是您在 64 位字中将奇数(设置了最低有效位的数字)左移 63 位。您获得的值为
0b1000_0000_0000_0000_...._0000
或
0x8000000000000000
那个(二进制补码)是你在问题中 post 的数字。
无论如何,将带符号的 64 位数字 移动 63 位是未定义的行为,因此这意味着您可以收到任何东西......如果是巨大的负数。