理解大端序和小端序
开始之前
文章正式开始之前,先来做一个小测试
前提
已知运行平台(x86_64,Linux,gcc 9.3.0)中,一个int数据类型的大小是4Byte。
也就是说,一个int类型的数据会占用内存中一块连续4Byte大小的区域。
有这么一个int十进制整数:305419896
,用十六进制表示的话就是0x12345678
使用4Byte(32bit) 的二进制表示的话,就是
[0] | [1] | [2] | [3] |
---|---|---|---|
00010010 (0x12) | 00110100 (0x34) | 01010110 (0x56) | 01111000 (0x78) |
C语言的内存魔法
既然一个int是占了4个Byte,那么有没有办法把每个Byte的内容单独取出来而不是把4个Byte作为一个int整体呢?
当然可以
这时候就要用到C语言神奇的指针和强制类型转换的
// 平平无奇的十六进制写法的int整数
int a = 0x12345678;
// 获取变量a的指针,并把指针类型强制类型转换成unsigned char*型
unsigned char * p = (unsigned char *)&a;
for(int i = 0; i < sizeof(int); i++) {
printf("%x ", p[i]); // 输出变量a内存地址起始位置开始,每Byte的十六进制内容
}
unsigned char * p = (unsigned char *)&a;
这么做的讲究是什么?
目的是因为int指针的每次做加减法运算时,地址偏移的单位都是4,而char型指针地址每次偏移的量是1,这样就能实现对一个长度为4Byte的int内存区域按每1Byte进行操作了
输出内容是啥?
也许你以为是0x12 0x34 0x56 0x78
吧。
实际上是:0x78 0x56 0x34 0x12
字节序
大小端序
震惊,居然是和我们人类直观的做法是倒着来的。
像上面这种对人类来说,本应该在内存最高位的数据,被放到内存最低位的字节顺序,就被称为小端序(Little-Endian)。
相反,和我们人类直观直觉相符合的,就是大端序了(Big-Endian)
为什么要有字节序
计算机内部基本的存储单位是Byte(字节),1Byte = 8bit,能存储的大小相当有限,数据之大,1Byte装不下的时候,就要用好几个Byte一起去存,比如1个int,就用到了4个Byte去存储。
既然你用了连续多个Byte存储,总得有个先后顺序对吧,所以这就产生了“字节序”的概念。
为什么我们的计算机采用了小端序
对于我们人类来说,进行加减乘除四则运算的时候,都是从个位数开始计算
比如12345 + 67,先算个位5+7=12,再算十位4+6+1(进位)=11,最后算百位3+1(进位)=4,最终结果12412
欸?发现了没?虽然我们数字书写是从左往右,但我们运算的时候,是从右往左,也就是先从低位开始计算。而正好我们的计算机电路在存取数据的时候,也是从地址的低位到高位的,于是乎科学家们干脆直接就让这种大于1Byte的数据采用小端序在计算机中进行存储和运算。
所有计算机/计算机的一切都是小端序么?
当然不是,PowerPC、IBM、Sun就是采用大端序存储的,而x86、DEC则采用了小端序。
大端序的好处:内存低位第一个就能读到符号位,判断正负很快啊!(马老师配音)
小端序的好处:前面说的运算高效方便,类型强转不需要重新调整(比如int转short,低位都不需要动的,高位不理就完事了)
而对于网络协议中使用的字节序,则统一规范使用了大端序,所以构造和解析网络协议报文的时候,就得根据主机自己的字节序来进行必要的转换了。
本机字节序的判断
使用C语言代码简单实现
#include <stdio.h>
#define BIGENDIAN 1
#define LITTLEENDIAN 0
int get_byte_seq() {
int static flag = -1; // 结果缓存,多次调用就不需要做重复运算了
if (flag == -1) {
int a = 0x12345678;
unsigned char * b = (unsigned char *)&a;
if (b[0] == 0x78) { // 低位的内存地址是数据的低位值,就是小端序
flag = LITTLEENDIAN;
} else {
flag = BIGENDIAN;
}
}
return flag;
}
int main(int argc, char const *argv[])
{
printf("字节序类型:%s\n", get_byte_seq() == BIGENDIAN ? "大端序" : "小端序");
return 0;
}
评论
ohhhhhhhhhhhΣ(っ °Д °;)っ
(((┏(; ̄▽ ̄)┛装完逼就跑