读书笔记--《深入理解计算机系统》第二章 信息的表示和处理

第二章 信息的表示和处理

1. 信息存储
①、1个字节=8位,大多数计算机将1个字节作为最小的可寻址的存储器单位。(单片机除外)
②、机器级程序将存储器(一般指内存)视为一个非常大的字节数组,称为 虚拟存储器
③、存储器的每个字节由一个唯一的数字标识,称为 地址,所有可能地址的集合称为 虚拟存储空间
④、每台计算机都有一个 字长:指明整数和指针数据的标称大小,决定了虚拟存储空间的最大值,即决定了寻址范围。
⑤、 大小端:
        大端法:高字节在低位,低字节在高位。
       小端法:低字节在低位,高字节在高位。

       例如:x = 0x12345678 在内存上的存储方式:(注间:12是高字节,78是低字节)
读书笔记--《深入理解计算机系统》第二章 信息的表示和处理_第1张图片
                                 
      现在许多处理器都使用 双端法,即用户可以通过配置来决定使用大端存储还是小端存储。
      PS 有一点需要注意的是:
            UDP/TCP/IP协议规定 网络字节序是大端法。进行网络编程的时候,发送数据时需要将本地字节序转换成网络字节序,接收到数据后需要将网络字节序转换成本地字节序。

2. C语言中的移位运算
   左移:x << k,丢弃左边最高的k位,并在右端补k个0。
   右移:x >> k,该行为有点微妙,可分为 逻辑右移算术右移
          逻辑右移:左端补K个0。
          算术右移:左端补K个最高有效位的值。
读书笔记--《深入理解计算机系统》第二章 信息的表示和处理_第2张图片
    C语言标准并没有明确规定应该使用哪种类型的右移。对于无符号数据(unsigned声明的整型对象),右移必须是 逻辑的。而对于有符号的数据,算术或逻辑都可以,因此潜在右移可移植性问题。但实际上,几乎所有编译器/机器组合,对有符号数据的右移都采用 算术右移。
    Java做得似乎更好一些,因为它对右移操作有明确的定义:x >> k 将x 算术右移k个位置,x>>>k将x 逻辑右移k个位置。

3.有符号和无符号之间的转换
   关于该内容,书上用了许多晦涩的数学工式来计算、表达,但是我觉得可以这么概括一下:C语言中,当有符号和无符号进行强制转换的时候,就是简单地 把表示该数字的二进制“解释”成有符号数或无符号数即可。是从位级角度来看,而不是数的角度。
   比如将有符号转成无符号:
        int y = -9;                     //二进制是:11111111111111111111111111110111 
        unsigned int x = (unsigned int)y;  //此时x的十进制值为:4294967287

4.无符号数运算
        C语言中的某些规定可能会产生令人意想不到的结果,如下所示的unsigned数据类型,虽然它概念上很简单,但可能导致即使资深程序员都意想不到的行为。
#include <stdio.h>
void main(void)
{
    unsigned int a = 1;
    unsigned int b = 10;
    int ret1 = (a - b > 0);
    printf("ret1 = %d\n", ret1);    //输出为1     无符号int相减,当计算结果为负数时,实际上被认为是一个很大的数。

    unsigned short c = 1;
    unsigned short d = 10;
    int ret2 = (c - d > 0);
    printf("ret2 = %d\n", ret2);   //输出为0     无符号short相减,在计算过程中先被提升为int类型,因此实际上是有符号参与运算的。
}

小结:
  看完本章需要极大的耐心,因为本章用了大量的数学工式。这些工式证明或总结了计算机对数据的处理方式,同时揭示了C语言的某些规定可能使程序产生安全漏洞。个人认为,无论是C语言还是IEEE相关标准,都是在遵循计算机工作方式的前提下,尽可能方便人类的思维习惯进行设计的。有些知识点直接影响到开发/调试质量和进度的需要重点掌握,比如大小端法、移位运算(驱动开发常用)、强制类型转换等;有些知识点了解一下有这么一回事就行,真正用到的时候可以再查阅更为详细的资料即可。





你可能感兴趣的:(读书笔记)