gpt4 book ai didi

c - C 中的位移位无符号长整型

转载 作者:行者123 更新时间:2023-12-04 00:18:30 26 4
gpt4 key购买 nike

我在我写的一段代码中发现了一个错误,并修复了它,但仍然无法解释发生了什么。它归结为:

unsigned i = 1<<31;          // gives 21476483648 as expected
unsigned long l = 1<<31; // gives 18446744071562067968 as not expected

我知道这里有一个问题: Unsigned long and bit shifting其中完全相同的数字显示为意外值,但在那里他使用了一个带符号的字符,我认为这导致了符号扩展。我真的一辈子都无法理解为什么我在这里得到了不正确的值。

我在 Ubuntu 18.04 上使用 CLion,在我的系统上使用 unsigned是 32 位和一个 long是 64 位。

最佳答案

在这个表达式中:

1<<31

1有类型 int .假设 int是 32 位宽,这意味着您将一点移入符号位。这样做是 undefined behavior .

这在 C standard 的第 6.5.7p4 节中有所记录。 :

The result of E1 << E2 is E1 left-shifted E2 bit positions; vacated bits are filled with zeros. If E1 has an unsigned type, the value of the result is E1×2E2, reduced modulo one more than the maximum value representable in the result type. 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.



但是,由于您使用的是使用 GCC 的 Ubuntu,因此行为实际上是实现定义的。 gcc documentation状态:

Bitwise operators act on the representation of the value including both the sign and value bits, where the sign bit is considered immediately above the highest-value value bit. Signed >> acts on negative numbers by sign extension.

As an extension to the C language, GCC does not use the latitude given in C99 and C11 only to treat certain aspects of signed << as undefined. However, -fsanitize=shift (and -fsanitize=undefined) will diagnose such cases. They are also diagnosed where constant expressions are required.



所以在这种情况下 gcc 直接作用于值的表示。这意味着 1<<31有类型 int和代表 0x80000000 .此十进制表示的值为 -2147483648。

当此值分配给 unsigned int 时, 它是通过 6.3.1.3p2 节中的规则转换的:

Otherwise, if the new type is unsigned, the value is converted by repeatedly adding or subtracting one more than the maximum value that can be represented in the new type until the value is in the range of the new type.



因为对于 32 位的“比最大值多一”是 42949672956 unsigned int这导致 int值 -2147483648 被转换为 unsigned int值 42949672956 -2147483648 == 2147483648。

1<<31分配给 unsigned long int这是 64 位,“比最大值多一个”是 18446744073709551616 所以转换的结果是 18446744073709551616 -2147483648 == 1844674407156206796,这是你得到的值

要获得正确的值,请使用 UL后缀使值 unsigned long :
1UL<<31

关于c - C 中的位移位无符号长整型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62388255/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com