文章目录
- 1 十进制数转为十六进制时,如何区分正负?
- 1.1 正数处理
- 1.2 负数处理
- 1.3 关键点
- 2 负数补码高位是1,那么一个很大的正数,高位也会出现1,会和负数搞混吗?
- 2.1 符号位明确区分
- 2.2 补码的数值范围不重叠
- 2.3 大正数的处理
- 2.4 编程语言的自动处理
- 2.5 总结
1 十进制数转为十六进制时,如何区分正负?
在C/C++中,整数(包括负数)在内存中都是以补码形式存储的
。代码利用了这一特性,通过位操作自动处理正负数的转换:
1.1 正数处理
- 例如 FocusStep = 4(二进制补码:00000000 00000000 00000000 00000100)
- 右移24位得到最高字节:0x00
- 右移16位:0x00
- 右移8位:0x00
- 直接取最低字节:0x04
- 结果:00 00 00 04
1.2 负数处理
- 例如 FocusStep = -5(二进制补码:11111111 11111111 11111111 11111011)
- 右移24位得到最高字节:0xFF(符号位扩展)
- 右移16位:0xFF
- 右移8位:0xFF
- 直接取最低字节:0xFB
- 结果:FF FF FF FB
**
1.3 关键点
- 右移操作会自动保留符号位(算术右移),
负数右移时会填充1
- & 0xFF操作截取最低8位,保证只取一个字节
- 整个过程完全依赖C语言的整数存储规则,无需手动区分正负
2 负数补码高位是1,那么一个很大的正数,高位也会出现1,会和负数搞混吗?
在C/C++中,整数的正负区分由最高位(符号位)决定,但不会因数值大小导致混淆,原因如下:
2.1 符号位明确区分
32位整数的最高位(第31位)为符号位:0表示正数,1表示负数。例如:
最大正数
0x7FFFFFFF(补码:0111 1111 1111 1111 1111 1111 1111 1111),- 符号位为0,其余31位全1,表示32位有符号整数的最大值 2³¹−1=2147483647;
最小负数
0x80000000(补码:1000 0000 0000 0000 0000 0000 0000 0000),-
符号位为1,其余31位全0,表示32位有符号整数的最小值 -2³¹ =−2147483648;
-
特殊性:该值是补码系统中唯一没有对应正数的负数(因正数范围无法表示2³¹);
-
2.2 补码的数值范围不重叠
正数范围:0x00000000 ~ 0x7FFFFFFF(0 ~ 2³¹-1)
负数范围:0x80000000 ~ 0xFFFFFFFF(-2³¹ ~ -1)
两者二进制表示完全互斥18。
2.3 大正数的处理
即使正数的高位字节包含0xFF(如 0x00FFFFFF),其符号位仍为0,不会与负数混淆。
例如:
- 0x00FFFFFF(16,777,215)是正数
- 0xFFFFFFFF(-1)是负数
2.4 编程语言的自动处理
位操作(如右移)会保留符号位特性,负数右移补1,正数补0,因此代码中无需手动区分。
2.5 总结
补码的设计保证了正负数二进制表示的唯一性,数值大小不会导致混淆。