C中的左移操作员给出了奇怪的结果



我有以下程序:

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个斑点移动将导致最右边的1最终以最左侧的二进制数字结束:

1000000000000000000000000000000000000000000000000000000000000000

在2的补充二进制中,是-9223372036854775808。

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

或者您甚至可以尝试此BITSHIFT计算器:https://bit-calculator.com/bit-shift-calculator

您的移位表达式具有未定义的行为。您没有任何价值从这种转变中有意义的期望。

在左移E1 << E2的C行为中,用于签名的E1由6.5.7/4

描述

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

问题在于,您剩下一个奇数数(一个数字最少的位置设置的数字(,左侧的63个位置为64位单词。您获得的价值是

0b1000_0000_0000_0000_...._0000

0x8000000000000000

(在两个补充中(是您在问题中发布的数字。

无论如何,转移63位a 签名的64位号是未定义的行为,因此这意味着您可以完全收到任何东西...事件,巨大的负数。

最新更新