我做了一个可重现的代码如下/
#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 和全零值,我该怎么办?
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);
}
改变
a |= (1 << 31);
到
a |= (1UL << 31);
1
是一个 int
常数,默认为 signed int
。
来自 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);