主要是关于主存中的地址以及数据的二进制表示
数据存储的基本形式
内存条:用来存放程序和数据的装置
C 语 言 | char、short、int、double |
对应长度 | 1个、 2个、 4个、8个字节 |
汇编语言 | byte word dword qword |
对应长度 | 字节 字 双字 四字 |
字节(Byte)是最小的寻址单位,每个字节都有一个地址,物理地址是唯一的,两个相邻的字节组成一个字(WORD),字地址是这2个字节中低字节的地址。同理,双字由连续4个字节组成,地址为4个字节中最低字节的地址。
位(Bit)是基本存储单位。
Q1:1M字节内存,地址编码需要多少二进制位?
Q2:32位地址对应的内存大小可达到多大?
4G
Q3:两个黄色的字节组成的字的地址是多少?字中的内容又是多少?红色的呢?
黄色:PA:00012346H 、DATA: 04F8H
红色:PA:00012347H、DATA: 5604H
地址为12346H的双字是: 44434241H,即(00012346H) = 44434241H
地址为12346H的字是: 4241H,即(00012346H) = 4241H
地址为12346H的字节是: 41H,即(00012346H) = 41H
数据存储方法有两种:
- 小端存储(Little Endian):低地址字节存放数据的低字节。
- 大端存储(Big Endian):与小端相反。
Intel x86 系列采用小端存储
给定一个地址后,可以根据该地址取一个字节、一个字、一个双字……取多少字节的数据,取决于地址类型。
数值数据在计算机内的表示形式
可以详见这一篇
常用的数值数据:二进制、十进制、十六进制、BCD码
常用的字符数据:ASCII (美国信息标准交换代码)、GB2312
定点表示法
小数点固定在第0位的后面。
有符号数的n位二进制的补码表示:
- 正数的补码是其本身;
- 负数的补码:先求其相反数的补码,然后对该补码的二进制逐位求反,最后加1。
设 n =16, -69DA H 的补码表示是多少?
- -69DA H 的相反数是 69DA H
- 对应的二进制是 0110 1001 1101 1010 B
- 逐位求反 1001 0110 0010 0101 B
- 加1后: 1001 0110 0010 0110 B
- [ -69DAH]补 = 9 6 2 6 H
注:一个二进制数的补码表示中,其最高位(即符号位)向左扩展若干位后,得到的仍然是该数的补码。
有符号数(补码表示)的大小比较:
5678H < 7345H
5678H > 8345H
3271H > 0A521H
0A521H < 0B521H
BCD码
BCD (Binary Coded Decimal):二进制编码的十进制
用4位二进制数表示一位十进制数。
1 = 0001 BCD 8 = 1000 BCD
2 = 0010 BCD 9 = 1001 BCD
……
BCD码可分为两类:有权BCD码和无权BCD码
- 有权BCD码:8421码、2421码、5421码
- 无权BCD码:余3码、余3循环码、格雷码
8421码:
8421码,是一种用二进制表示十进制数字的编码方式。每个十进制数字0-9都用4位二进制数来表示。每一位的权值分别为8、4、2和1,因此称为8421码。例如:
数字0的8421码表示为0000
数字1的8421码表示为0001
数字9的8421码表示为1001
2421码:
2421码是一种用二进制表示十进制数字的编码方式。它与8421码类似,但权值规定不同。在2421码中,权值分别为2、4、2和1,因此称为2421码。例如:
数字0的2421码表示为0000
数字1的2421码表示为0001
数字9的2421码表示为1001
5421码:
5421码是一种用二进制表示十进制数字的编码方式。类似于8421码和2421码,但权值分别为5、4、2和1,因此称为5421码。例如:
数字0的5421码表示为0000
数字1的5421码表示为0001
数字9的5421码表示为1001
余3码(Excess-3码):
余3码是一种用于表示十进制数字的二进制编码方式。它通过给定的十进制数字加上3后,将结果转换为二进制表示。每个十进制数字用4位二进制数表示。例如:
数字0的余3码表示为0011
数字1的余3码表示为0100
数字9的余3码表示为1100
余3循环码(XS-3码):
余3循环码,也称为Gray-Excess-3码,是一种用于表示十进制数字的二进制编码方式。它是在余3码的基础上应用格雷码的编码规则得出的。不同于一般的格雷码,余3循环码的转换规则是:当前位与前一位的异或结果作为当前位的值,首位与尾位也进行异或。这样可以确保相邻两个码之间只有一个比特的差异。
例如:数字0的余3循环码表示为0011
数字1的余3循环码表示为0100
数字9的余3循环码表示为1011
格雷码(Gray Code):
格雷码是一种二进制数码系统,其中连续的数字只有一位二进制数不同。相邻两个码之间只有一个位的改变,这样可以减少误码产生的可能性。例如:
数字0的格雷码表示为0000
数字1的格雷码表示为0001
数字9的格雷码表示为1011格雷码在数字转换和数字传输中有广泛的应用,因为它可以减少数字转换过程中的错误和噪声对数字接收的影响。
字符数据在机内的表示形式
ASCLL码:
汉字编码 - GB2312 :
GB2312是简体中文字符集,包含了6763个汉字和682个非汉字字符(图形符号),双字节编码。所有字符组成一个94x94的矩阵。矩阵的每一行称为一个“区”,每一列称为一个"位"(行列号称为区位号)。
- 01-09区为682个非汉字字符(图形符号)
- 16-55区为一级汉字(3755个最常用的汉字,按拼音字母顺序排列)
- 56-87区为二级汉字(3008个汉字,按部首次序排列)
- 10-15区、88-94是空白区(保留区)。
区位码:由行号(区号)为高字节、列号(位号)位低字节组成的字
国际码(交换码):区位码 + 0x2020(似乎没什么用)
机内码:区位码 + 0xA0A0
‘华’:区位码 = 27 10,即 0x1B0A
国际码 = 0x3B2A
机内码 = 0xBBAA(计算机存贮)
Unicode:
- 码点U+0041:英语的大写字母A;
- 码点U+534E:汉字“华”
- Unicode 的实现方式:UTF-8、UTF-16、UTF-32
在Unicode 7.0版中,收入了109449个符号,其中的中日韩文字为74500个。最前面的65536个字符位,码点从 U+0000 到 U+FFFF。称为基本平面(BMP),含最常见的字符。
Unicode存在的问题:
- 如果所有字符都用2个字节、3个字节甚至更多字节来表示,会造成存储空间的增加,太费存储空间
- ASCII只需要一个字节来进行编码
- 如何区别该编码是Unicode还是ASCII ?
UTF-8
- 是一种变长的编码方法,长度从1个到4个字节不等;
- 越是常用的字符,字节越短;
- 对于单字节的符号:字节的第一位设为0,后面7位为这个符号的Unicode码;对于英文字母,UTF-8 编码和 ASCII 编码是相同的。
- 对于n字节的符号(n>1):第一个字节的前n位都设为1,第n+1位设为0,后面字节的前两一律设为10,剩下没有提及的二进制位,全为这个符号的 Unicode 码。
UTF-16
- 介于UTF-8和UTF-32之间,结合了定长和变长两种编码方式的特点;
- 基本平面的字符用2个字节,辅助平面的字符用4个字节。
- 2个字节(U+0000 到 U+FFFF):UTF-16编码就是码对应的16位无符号整数
- 4个字节(U+010000 到 U+10FFFF):先计算 U’= U - 0x10000,将U'写成二进制形式:yyyy yyyy yyxx xxxx xxxx,U的UTF-16编码:110110yyyyyyyyyy 110111xxxxxxxxxx。
UTF-32
- UTF-32是最直观的编码方法
- 每个码点使用四个字节表示
- 字节内容一一对应码点
- 转换规则简单直观,查找效率高。缺点在于浪费空间
- 同样内容的英语文本,它会比ASCII编码大四倍。
- 实际上几乎不使用这种编码方法,HTML 5标准就明文规定,网页不得编码成UTF-32。
ANSI 编码
- 不同的国家和地区制定了不同的标准
- 在简体中文Windows操作系统中,ANSI编码代表GB编码;
- 在日文Windows系统中,ANSI编码代表 Shift_JIS 编码。
- 不同 ANSI 编码之间互不兼容;
- 对于ANSI编码而言,0x00 ~ 0x7F之间的字符,依旧是1个字节代表1个字符。
数据类型转换(整数)
不同整数类型的变量赋值,如何进行转换?
- 规则1:两边的长度一样,直接复制,与类型无关;
- 规则2:右边长,左边短,截断,保留低位;
- 规则3:右边短,左边长,右边的数需要扩展(以右边的类型进行扩展,与赋值号左边变量的类型无关)。
short s1 = 0xffff;
unsigned short s2 = 0xffff;
int i1;
i1 = s1; // i1=0xffffffff;
i1 = s2; // i1=0x0000ffff;
short s1 = 0xffff; //s1=-1;
unsigned short s2 = 0xffff; //s2=-1;
int i1; unsiged int i2;
i1 = s1; // i1=0xffffffff;
i1 = s2; // i1=0x0000ffff;
i2 = s1; // i2=0xffffffff;
i2 = s2; // i2=0x0000ffff;
//结论:以右边的类型进行扩展;与 赋值号 左边变量的类型无关
浮点数据在机内的表示形式
规格化数据:
科学表示法:小数点左边恒为1
要素:正负号、尾数 XXXX、指数 n
符号位:0表示正数,1表示负数
指数:采用移码来表示。单精度移 7F
-126 D -> 00000001 B
127 D -> 11111110 B
尾 数:用原码表示。对于规格化浮点数,尾数的小数点前面的 1 不需存贮。
符号位:0表示正数,1表示负数
指数:采用移码来表示。双精度移 3FF
-1022D -> 000 0000 0001B
1023D -> 111 1111 1110B
高精度移 3FFF
Q:规格化浮点数能表示0和很小的数(如 2^-130 )吗?
不能,比如对于区间(-1.4013*10-45, 0)、(0, 1.4013*10-45)的数,float是无法表示的
Q:为什么指数使用移码表示,而不是补码表示?
在加法运算时,要对阶,用无符号数比较、移位更简单。
Q:为什么规格化时,用 ±1.XXXX * 2^n B ,而不是 ±0.1XXXX * 2^n B ?
能够保存更多的有效位数,指数的表示范围也更大。
特殊数值
+∞ 符号位0、阶码全1、尾数为0
0-1111111 1-0000000 00000000 00000000
-∞ 符号位1、阶码全1、尾数为0
1-1111111 1-0000000 00000000 00000000
NaN (Not a Number) 符号位1或0、阶码全1、尾数不为0
例如: 0-1111111 1-0000000 00000000 00000001
一些因素会引起 NaN(非数值),如 0 / 0、sqrt(-1) 等。
+0 符号位0、阶码全0、尾数为0
0-0000000 0-0000000 00000000 00000000
-0 符号位1、阶码全0、尾数为0
1-0000000 0-0000000 00000000 00000000
绝对值越大,浮点数分布越稀疏,不满足结合律(即(大数 + 较小数 )- 大数 不一定等于该较小数)
浮点数不能精确表示一些十进制数
int 与float在整数部分仅部分重叠
i == (int)(float)i不成立
int是double的子集
i==(int)(double)i成立
float数据集是double的子集
f==(float) (double) f 成立