第二章 信息的表示和处理
![](https://img-blog.csdn.net/20140224150523265?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvZ2Fuc2h1eXU=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
1. 信息存储
①、1个字节=8位,大多数计算机将1个字节作为最小的可寻址的存储器单位。(单片机除外)
②、机器级程序将存储器(一般指内存)视为一个非常大的字节数组,称为
虚拟存储器。
③、存储器的每个字节由一个唯一的数字标识,称为
地址,所有可能地址的集合称为
虚拟存储空间。
④、每台计算机都有一个
字长:指明整数和指针数据的标称大小,决定了虚拟存储空间的最大值,即决定了寻址范围。
⑤、
大小端:
大端法:高字节在低位,低字节在高位。
小端法:低字节在低位,高字节在高位。
例如:x = 0x12345678 在内存上的存储方式:(注间:12是高字节,78是低字节)
现在许多处理器都使用
双端法,即用户可以通过配置来决定使用大端存储还是小端存储。
PS 有一点需要注意的是:
UDP/TCP/IP协议规定
网络字节序是大端法。进行网络编程的时候,发送数据时需要将本地字节序转换成网络字节序,接收到数据后需要将网络字节序转换成本地字节序。
2. C语言中的移位运算
左移:x << k,丢弃左边最高的k位,并在右端补k个0。
右移:x >> k,该行为有点微妙,可分为
逻辑右移和
算术右移。
逻辑右移:左端补K个0。
算术右移:左端补K个最高有效位的值。
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类型,因此实际上是有符号参与运算的。
}
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相关标准,都是在遵循计算机工作方式的前提下,尽可能方便人类的思维习惯进行设计的。有些知识点直接影响到开发/调试质量和进度的需要重点掌握,比如大小端法、移位运算(驱动开发常用)、强制类型转换等;有些知识点了解一下有这么一回事就行,真正用到的时候可以再查阅更为详细的资料即可。