代码改变世界

CSAPP:第二章学习笔记:斗之气2段

2019-03-20 17:34  剑动情缥缈  阅读(400)  评论(0编辑  收藏  举报

一、字长:虚拟地址通过一个字来编码,字长为32位,则可以标识2^32个地址空间,每个空间为一个字节,故为4G

二、字节序:当解释多个字节类型时,存在大小端字节序问题

  0x1234567,在大小端表示法下的内存模型

  

三、整数表示

  1.无符号数编码:针对整数和零

  

  2.补码编码:针对有符号数,可以为正、零或者负数(最大负数表示为100000..0,-1表示为11111...1)

  

  

  3.有符号与无符号之间的转换

  1)转换前后长度一致:位值不变,只是改变了解释方式

  2)转换后长度变长:

  • 无符号数:零扩展
  • 有符号数:符号扩展

  3)转换后长度变短:截断后依据类型解释

四、整数运算

  1.无符号加法

  

  2.补码加法:

  

  3.无符号数乘法:注意负数

  4.补码乘法:注意负数

  5.加法、减法、位级运算和移位只需要一个cycle,乘法需要10个或者更多,除法需要30个或者更多,编译器会进行优化,左移等于乘以2,右移等于除以2

五、浮点数

  1.表示

  1)定点:难以表示很大的数,如5*2^100,需要101后面跟100个0

  

  2)实际采用如下表示方法

  对于

  • 符号:单独的符号位s,s=1表示负数,s=0表示正数
  • 尾数:n位小数字段编码尾数M,单精度float中n=23,双精度double中n=52
  • 阶码:k位阶码字段编码阶码E,单精度float中k=8,双精度double中k=11

  具体解释分三种情况:规格化的、非规格化的、无穷大与NaN

六、测试大小端字节序及补码

  1.字节序:12345在ubuntu上按内存地址从小到大表示为39300000,0x3039对应12345,所以是小端表示法(低地址存放低位字节)

  2.int与float:强转后,float中部分bit位和int表示中会有对齐,因为float与int表示数值方式不同

  3.负数使用补码表示:采用小端序,值为FFFFCFC7,即为-12345的补码表示,可以通过上述补码公式验证

  输出结果:

  

#include <stdio.h>

typedef unsigned char *byte_pointer;

void show_bytes(byte_pointer start, int len) {
        int i;
        for (i = 0; i < len; i++)
                printf(" %.2x", start[i]);
        printf("\n");
}

void show_int(int x) {
        show_bytes((byte_pointer) &x, sizeof(int));
}

void show_float(float x) {
        show_bytes((byte_pointer) &x, sizeof(float));
}

void show_pointer(void *x) {
        show_bytes((byte_pointer) &x, sizeof(void *));
}

void test_show_bytes(int val) {
        int ival = val;
        float fval = (float) ival;
        int *pval = &ival;
        show_int(ival);
        show_float(fval);
        show_pointer(pval);
}

int main() {
    int val = 12345;
    test_show_bytes(val);
    test_show_bytes(-val);
    return 0;
}