浅谈C语言中的有符号和无符号数的转化(读《深入理解计算机操作系统(第三版)》有感)
通常在计算机系统里,一个字节由8位组成,范围即为
[
0
,
255
(
2
8
−
1
)
]
[0,255(2^8-1)]
[0,255(28−1)]。
计算机系统里,通常声明的类型的字节数和范围如下:
有符号 | 无符号 | 32位 | 64位 |
---|---|---|---|
char | unsigned char | 1 | 1 |
short | unsigned short | 2 | 2 |
int | unsigned int | 4 | 4 |
long | unsigned long | 4 | 8 |
int32_t | uint32_t | 4 | 4 |
int64_t | uint64_t | 8 | 8 |
void * | 4 | 4 | |
float | 4 | 4 | |
double | 8 | 8 |
对于任意有符号类型,若字节数为w
,那么其范围为
[
−
2
8
∗
w
−
1
,
2
8
∗
w
−
1
−
1
]
[-2^{8*w-1}, 2^{8*w-1}-1]
[−28∗w−1,28∗w−1−1];
对于任意无符号类型,若字节数为w
,那么其范围为
[
0
,
2
8
∗
w
−
1
]
[0, 2^{8*w}-1]
[0,28∗w−1];
例如:
32位下的int类型,占用4个字节,其范围为
[
−
2
31
,
2
31
−
1
]
[-2^{31}, 2^{31}-1]
[−231,231−1],64位下的unsigned long类型,占用8个字节,其范围为
[
0
,
2
64
−
1
]
[0, 2^{64}-1]
[0,264−1]。
下面介绍数据在计算机中的存储方式,包括原码,反码,补码。
对于正整数而言,其原码,反码,补码相同,就是二进制码,例如:
short x = 53191;
其二进制表示为
1100
,
1111
,
1100
,
0111
1100,1111,1100,0111
1100,1111,1100,0111,其原码,反码,补码都是这样的。
对于负数而言,就多了一位符号位,符号位在首位,例如:
short x = 12345;
其二进制表示为 0011 , 0000 , 0011 , 1001 0011,0000,0011,1001 0011,0000,0011,1001,那么-12345的原码就是在此基础上,将首位的零变成符号位1即 1011 , 0000 , 0011 , 1001 1011,0000,0011,1001 1011,0000,0011,1001。
short x = -12345;
//原码:1011,0000,0011,1001
//反码:1100,1111,1100,0110(在原码基础上,符号位不变,其余取反)
//补码:1100,1111,1100,0111(在反码基础上加1)