深入理解操作系统(3)第二章:信息的表示和处理(2)整数表示(包括:有符号,无符号的二进制表示/反汇编器/-12345表示/反汇编器/C语言默认有符号/零扩展,符号扩展/截断数字/建议不使用无符号数)
1. 整型数据类型大小
2.8
2. 无符号和二进制补码编码
看之前请参考博客:详细讲解有符号数和无符号数
有符号数和无符号数详解
https://blog.csdn.net/lqy971966/article/details/106033332
有符号数和无符号数详解(2)补码详解
https://blog.csdn.net/lqy971966/article/details/106130830
1.大多数数字默认都是有符号的
如: int i = 12345; //它是有符号的
要创建无符号就显示说明: unsigned int i = 12345;
2.1 无符号的二进制表示 B2Uw
2.1.1
w表示位
最小值:[00……0] 即0
最大值:[11……1] 即2的w次幂-1
2.2 有符号的二进制表示 B2Tw
有符号数通过二进制补码表示
2.1.2
最高位表示符号位。1表示负数,0表示非负。
最小值:[10……0] 即8位下为 1000 -8
最大值:[01……1] 即8位下为 0111 7
2.2.1 有趣的数字(0 -1 最大最小有/无符号数)
2.9
2.2.2 12345 和 -12345的二进制表示
12345
二进制: 0011 0000 0011 1001
十六进制:0x3039
-12345
二进制: 1100 1111 1100 0111 补码表示(其无符号为: 53191)
十六进制: 0xCFC7 有符号数为:-12345 无符号数为:53131
因为:
1000 0000 0000 0000 表示 -32768
0100 1111 1100 0111 表示 20423
-32768+20423=-12345
32位ffffcfc7 有符号也是 -12345
因为:
0x7fffcfc7 2147471303
0x80000000 -2147483648
-2147483648+2147471303= -12345
2.2.3 反汇编器
反汇编器是一种将可执行程序文件转换回可读的ASCII码形式的程序。
这些文件包含许多十六进制数字,典型地都是用二进制补码的形式表示的。
能否认识这些数字并理解他们的意义(它们是正数还是负数)是非常重要的。
例子:
2.2.3
3. 有符号数和无符号数之间的转换
一堆公式……
4. C中的有符号与无符号数
4.1 数字默认都是有符号的
1.大多数数字默认都是有符号的
如: int i = 12345; //它是有符号的
要创建无符号就显示说明: unsigned int i = 12345;
2.几乎所有的机器都是使用二进制补码
4.2 有符号和无符号运算,有符号强制转换为无符号数
有符号和无符号运算,有符号强制转换为无符号数,并假设这两个数都是非负的,来执行这个运算。
c允许无符号数和有符号数之间的转换。原则是:基本的位表示保持不变。
5. 扩展一个数字的位表示(零扩展,符号扩展)
零扩展:
要将一个无符号数转换为一个更大的数据类型,我们只要简单地在表示的开头添加0。
这种运算被称为零扩展
符号扩展:
要将一个二进制补码数字转换为一个更大的数据类型,规则是执行一个符号扩展
在表示中添加最高有效位的值。
例子说明:
short sx = -12345;
unsigned short usx=sx; /* 53191 */
int x=sx;
unsigned ux=usx;
printf("sx=%d,%x\n",sx,sx);
printf("usx=%d,%x\n",usx,usx);
printf("x=%d,%x\n",x,x);
printf("ux=%d,%x\n",ux,ux);
结果:
sx=-12345,ffffcfc7 /* 这里已经默认扩展了 */
usx=53191,cfc7
x=-12345,ffffcfc7
ux=53191,cfc7
说明:
-12345和53191的二进制表示是相同的:CFC7
扩展到32位,-12345的二进制为: ffffcfc7 ->符号扩展
扩展到32位,53191的二进制为: 0000cfc7 ->0扩展
16位cfc7 有符号数 就是 -12345
因为:
1000 0000 0000 0000 表示 -32768
0100 1111 1100 0111 表示 20423
-32768+20423=-12345
32位ffffcfc7 有符号也是 -12345
因为:
0x7fffcfc7 2147471303
0x80000000 -2147483648
-2147483648+2147471303= -12345
6. 截断数字
例子:
int x = 53191;
short sx=(short)i;
int x2=sx;
printf("x=%d,%x\n",x,x);
printf("sx=%d,%x\n",sx,sx);
printf("x2=%d,%x\n",x2,x2);
结果:
x=53191,cfc7 /* 53191二进制: 1100 1111 1100 0111 */
sx=-12345,ffffcfc7 /* -12345二进制: ff ff 1100 1111 1100 0111 补码表示 */
x2=-12345,ffffcfc7 /* 扩展到32位,-12345的二进制为: ffffcfc7 ->符号扩展 */
说明:
16位 cfc7 有符号数 就是 -12345
32位 ffffcfc7 有符号也是 -12345
因为:
0x7fffcfc7 2147471303
0x80000000 -2147483648
-2147483648+2147471303= -12345
7. 关于有符号数与无符号数的建议
就像我们看到的那样,有符号数到无符号数的隐式强制类型转换导致了某些与直觉不相符行为。
而这些觉不相符的特性经常导致程序错误,并且包含隐式强制类型转换的细微差别的错误很难被发现。
建议:
避免这类错误的一种方法就是绝不使用无符号数。
实际上,除了C以外很少有语言支持无符号整数。
很明显,这些其他语言的设计者认为它们的麻烦要比益处多得多。
比如,Java只支持有符号整数,并且要求以二进制补码运算来实现。