C中的左移运算符给出奇怪的结果

时间:2019-05-10 16:48:47

标签: c bit-shift

我有以下程序:

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

这是为什么?

3 个答案:

答案 0 :(得分:5)

如果将这些整数转换为带符号的2的补码二进制,则可以了解原因:

241294423792285589以二进制形式是

0000001101011001010000000000000000000000011010111111011110010101

向左移动63个点将导致最右边的1以最左边的二进制数结尾:

1000000000000000000000000000000000000000000000000000000000000000

2的补码二进制为-9223372036854775808。

您可以在线找到二进制<->十进制转换器(例如https://www.rapidtables.com/convert/number/decimal-to-binary.html),可以使这一点更加清楚。

或者您甚至可以尝试使用以下移位计算器:https://bit-calculator.com/bit-shift-calculator

答案 1 :(得分:4)

您的班次表达式具有未定义的行为。您可以从这种转变中毫无意义地期待任何价值。

在C中,有符号的E1 << E2左移E1的行为由6.5.7 / 4描述

  

如果E1具有带符号的类型且非负值,并且E1×2 E2 在结果类型中可表示,则为结果值;否则,行为是不确定的。

答案 2 :(得分:0)

问题是您将一个奇数(设置了最低有效位的数字)左移了63位(在64位字中)。您获得的价值是

0b1000_0000_0000_0000_...._0000

0x8000000000000000

(以二进制补码)是您在问题中发布的号码。

无论如何,将63移位会放置一个带符号的64位数字是不确定的行为,因此这意味着您可以接收到任何东西...如果出现巨大的负数,则为空。