内存地址概念
内存字节地址(单位是字节,是最小可寻址地址单位)
0 1 2 3 4 5 6 ... N
- - - - - - - - -
每个字节内部bit位也有地址编号(这个地址无法通过机器指令寻址)
0 1 2 3 4 5 6 7
- - - - - - - -
一个4字节整数的地址结构如下
字节0 字节1 字节2 字节3
01234567 01234567 01234567 01234567
| |
字节内第0bit,整数内第0bit 字节内第7bit,整数内第31bit
CPU根据地址总线来寻址,比如一个4字节整数保存在内存0 1 2 3这4个字节中,给地址总线传入地址0就能读取这4个字节(32bit位)数字
字节序概念
一个多字节数据(处理器支持的原始数据 比如整数 短整数等等,结构体这种数据结构不算),内部字节排序不是唯一的,根据CPU不同分为两种
litte-end和big-end
对一个整数0x12345678
在litte-end机器中的存储分配是
78 56 34 12 (字节地址从低到高) 就是数据逻辑上的高字节 存储在内存地址的高字节
在big-end机器中的存储分配是
12 34 56 78 (字节地址从低到高) 就是数据逻辑上的高字节 存储在内存地址的低字节
这个就是字节序概念
比特序概念
一个byte数据,内部的8位bit 也有排序,根据CPU不同分为2种
litte-bit-end
big-bit-end
一个字节数 0x83(二进制表示为10000011)
在litte-bit-end机器中中存储分配(针对内存地址顺序)是
11000001 (bit位地址 从低到高) 就是数据逻辑上的高bit 存储在内存地址的高bit位
在big-bit-end(针对内存地址顺序)
10000011 (bit位地址 从低到高) 数据逻辑上的高bit 存储在内地地址的低bit位
这个就是bit序的概念,和字节序类似
比特序影响
目前计算机外设(包括网卡,硬盘等等)和CPU之间通过外部总线能自动正确的转换bit序,因为计算机外设交换都是字节流,而字节内部的bit序又自动转换了,所以这个基本没有影响
字节序影响
涉及二进制多字节数据传输,存储等外部交换数据时,需要程序转换字节序,否则对方会因为字节序不一致导致解析错误
比如一个整数 直接发送给另外一个字节序不同的计算机,没有转换字节序,那对方就无法正确解析;
同样的,一个整数写入磁盘,把这个文件拷贝给其他不同字节序的计算机系统,计算机读取后,虽然bit序正确,但是字节序不一致,导致解析错误
编程注意点
1.网络发送二进制数据,注意转换字节序
2.二进制文件共享,注意约定双方的字节序
3.C语言位域操作
这个需要说明一下
如下结构体
struct tm
{
char t1:3,
t2:2,
t3:1;
};
一般C编译器会按位域定义顺序 分配位域存储地址(字节内bit地址),从字节内 低bit地址开始分配,分配如下
0 1 2 3 4 5 6 7
| | | | |
------ ----- |
| | |
t1 t2 t3
在大端和小端机器上分配都是一样的,不过大端小端机器上生成的位域访问的汇编代码就不同了;
在小端机器上访问t1,访问的是byte中的地址前3bit
而在大端机器上访问t1,访问的也是byte中的地址前3bit
这样的话,从小端传递过的数据到了大端后,bit序反转了,小端低bit地址(数据低位) 就到了大端高bit地址(数据低位),而大端机器访问t1时还是访问从低bit位开始的3个bit,导致访问不正确;
这种情况,需要在定义结构体的时候,根据机器大小端,反序位域定义顺序,这样子就能正常访问了
struct tm
{
#ifdef litte_end
char t1:3,
t2:2,
t3:1;
#else
char t3:1,
t2:2,
t1:3;
#endif
};