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 位是未定义的行为,因此这意味着您可以收到任何东西......如果是巨大的负数。