执行a |= (1 << 31)得到意外值,求原因及正确实现方法
问题原因
你遇到的是有符号整数的符号扩展问题:
- 代码里的
1是默认的int类型(多数平台为32位有符号整数),1 << 31会让这个32位int的最高位(符号位)变为1,此时它的值是十进制的-2147483648。 - 当把这个有符号int值赋值给64位的
long int时,C语言会执行符号扩展:将原数的符号位(1)填充到新类型的所有高位,也就是把64位long的前32位全部填成1,最终得到0xffffffff80000000。
解决方法
要避免符号扩展,只需让移位操作的源数为long int类型即可,有两种简单实现方式:
方式1:使用long类型字面量
把1改成1L(明确声明为long int),这样移位操作会在64位空间内进行,不会触发符号扩展:
#include <stdio.h> int main(void) { long int a = 0x0; a |= (1L << 31); // 用1L替代1 printf("a: 0x%lx\n", a); }
输出结果为a: 0x80000000,对应64位的0x0000000080000000(printf的%lx不会打印前导零,但实际内存中高位为0)。
方式2:直接使用十六进制字面量
如果目标位固定,也可以直接给a赋值目标十六进制值,更直观:
#include <stdio.h> int main(void) { long int a = 0x80000000L; // 直接赋值目标值 printf("a: 0x%lx\n", a); }
内容的提问来源于stack exchange,提问作者Jason Park
相关产品推荐
相关产品推荐

