a |= (1 << 31) results in unexepected value

问题描述 投票:0回答:3

我做了一个可重现的代码如下/

#include <stdio.h>

int main(void)
{
    long int a = 0x0;

    a |= (1 << 31);

    printf("a: 0x%lx\n", a);

}

我希望'a'应该是0x0000000080000000.

但是给出的值是

a: 0xffffffff80000000.

为什么高 32 位以编程方式填充 1,如果我想将 'a' 设置为单个 1 和全零值,我该怎么办?

c bit
3个回答
2
投票

1
是一个
signed int
。当您将它向左移动 31 位时,您会得到负数
INT_MIN
(假设 32 位整数和二进制数)。然后,当您将它分配给
long int
(假设 64 位)时,它被签名扩展为具有相同的负值。

您需要改用无符号数:

int main(void)
{
    long int a = 0x0;

    a |= (1U << 31);

    printf("a: 0x%016lx\n", a);

}

https://godbolt.org/z/G95GYffPM

或者您需要在二进制或.

之前将其转换为
unsigned int

int main(void)
{
    long int a = 0x0;

    a |= (unsigned int)(1 << 31);

    printf("a: 0x%016lx\n", a);

}

https://godbolt.org/z/bq3j4dWsc


1
投票

改变

a |= (1 << 31);

a |= (1UL << 31);

1
是一个
int
常数,默认为
signed int


1
投票

来自 C 标准(6.5.7 移位运算符)

3 对每个操作数执行整数提升。这 结果的类型是提升后的左操作数的类型。

所以这个语句中使用的表达式

( a << 31 )
的类型

a |= (1 << 31);

是有符号整数类型

int
.

进一步(相同的C标准部分)

4 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. 如果 E1 有符号类型并且 非负值,并且 E1 × 2E2 在结果类型中是可表示的, 那就是结果值;否则,行为是 未定义。

假设

int
类型的对象包含
32
位并且最高有效位是符号位,那么表达式
(1 << 31 )
的值在
int
类型的对象中不可表示,因此 teh表达式调用未定义的行为。

您需要至少使用无符号整数类型

unsigned int
例如

a |= (1u << 31);

或无符号长整型

a |= (1lu << 31);

注意结果取决于类型的大小

long int
。它可以等于
4
作为类型
int
的大小或
8
作为类型
long long int
.

而不是在

0x
的调用格式字符串中手动编写
printf

printf("a: 0x%lx\n", a);

你可以使用标志

#
喜欢

printf("a: %0#16lx\n", a);
© www.soinside.com 2019 - 2024. All rights reserved.