《深入理解计算机系统》的确是一本让coder们拨云见日的秘籍。第二章信息的表示和处理,总结一下。
1、在对象的寻址上,几乎所有的计算机,把多字节对象都存储为连续的字节序列,对象的地址为所使用字节序列中最小的地址。
2、在存储对象字节的顺序上,分为小端机和大端机。小端机,按照最低有效字节到最高有效字节顺序存储对象。大段机,按照最高有效字节到最低有效直接存储数据。
假设变变量a的类型int,位于地址0x100处,它的值为0x01234567。地址范围为0x100~0x103。大小端机的存储如图所示:
大端机:
小端机:
判断大段机小段机的代码
//返回1表示是小段机,返回0表示大段机
int is_little_endian()
{
unsigned a=0x1;
unsigned char* bytepoint=(unsigned char*)&a;
if(bytepoint[0]==0x1)
return 1;
return 0 ;
}
3、c中的移位运算。
对于左移运算只有一种处理方式,就是在左移k位后,丢弃k个高位,并在右端补k个0。而右移运算,分为逻辑右移和算术右移。逻辑右移在左端补k个0。算术右移,在左端补k个最高有效位的拷贝。c语言标准没有明确的定义使用哪种类型的右移。对于无符号数据,右移必须是逻辑右移,而对于有符号数据两种右移都可以,这会导致可移植性问题。实际上几乎所有编译器/机器组合对有符号数据使用算术右移。
判断逻辑右移和算术右移的代码:
//有符号数据右移类型判断返回1表示算术右移,0表示逻辑右移
int is_shifts_are_arithmetic()
{
int a=-1;
a>>=1;
if(a>0)
return 0;
return 1;
}
//无符号右移类型判断
int unsigned_shift_are_arithmetric()
{
unsigned a=~0;
if(a==(a>>1))
return 1;
return 0;
}
4、整型表示
无符号整型(U),有符号整型(T),以B表示二进制数,w表示有效位数。
B2U表示二进制数据转化成无符号整型。
B2T:表示二进制数据转化成有符号数据。
U2T:无符号数据转化成有符号数据。
T2U:有符号转化成无符号数据。

c语言在处理同时包含有符号和无符号的表达式时,会隐含的将有符号转化成无符号,并假设这两个数都是非负的来执行这个运算。这对于标准的算术运算并无差异,但对关系运算来说,它会导致与直觉不相符的结果。当一个有符号和无符号数据比较是会将有符号数据转化成无符号数据在比较大小。如c语言在判断表达式(-1<0U)时表达式不成立。使用T2U将-1转化为无符号数为Umax。所以c执行的结果是(-1>0U),这与实际不符合。
注意在编译器处理一个形为-X的表达式的方法是首先读取表达式X然后对它取反,所以在32位的整型上,将Tmin32=-2147483648时会产生溢出,所以将Tmin32=-2147483647-1。
5、扩展一个数字的位表示
c语言中在不同字长的整型之间转换,在无符号数转化为一个更大的数据类型是,在开头添加0,称为零扩展。在将有符号转化为一个更大的数据类型是,执行符号扩展,在表示中添加最高有效位的值。
6、整数运算
无符号加法:当产生溢出的时候,所做的处理时丢弃高位数据。
有符号加法:
无符号乘法:
有符号乘法:
c语言中对于除2的幂运算,x/y=(x<0?(x+y-1):x)/y。
7、浮点数。
浮点标准表示,其中s决定正负数,m是有效位,e是指数。
c语言中有单精度float和双精度double,其中float是32位,s是1位,e是8位,m是23位。
double是64位,s是1位,e是11位,m是52位。
浮点数根据m位的值,分为规格化值,非规格化值,特殊值。
规格化,当m的位不全是0也不全是1时,浮点数属于规格化值。
非规格化,当e的位为全0时,浮点数属于非规格化值。这时E=1-Bias。费规格化给出了浮点0的表示它有+0.0和-0.0两种。
特殊值,当指数全为1时,在小数域全为0时,当s=0是正无穷,当s=1是负无穷。当小数域为非零时,结果成为“NaN”。不是一个数。
而对于计算机浮点运算需要注意的是它不满足结合性和分配性。
也就是说(3.14+1e10)-1e10的值为0.0而,(3.14+(1e10-1e10)=3.14。
浮点运算时使用了寄存器,而寄存器的位数可能比存储器表示浮点数可用的位数多。所以计算算计可能对原来的浮点数进行精度扩展。在Intel IA32上,就是一个80位的浮点寄存器。也就是不管是单精度还是双精度在从存储器读入浮点寄存器,都会变成扩展的精度格式。等再次写入时又会转化为单精度或是双精度,这是会由于舍入、下益或是上溢,改变它的值。这种直接的后果是如果同一个浮点数从存储器获取的值,和从寄存器获取的值是不相等的。