最近被人家问到关于字节序的问题,以前一般也没有怎么关心这方面的问题,不过怎么说这个也是一个基础的问题,今天就此就做个简单的记录:
程序之间的通信,其实就是发送数据流,字节(byte)被看作是数据的最小单位,一个字节中还包含8个比特(bit),这个是基础的计算机知识了,隐约中记得,这个在
我还没学习编程之前其实都已经明白这个东西了,貌似是高中有个数学课程里面提到过的,那时候记忆得比较清楚;
在一个32位的CPU中“字长”为32个bit,也就是4个byte。在这样的CPU中,总是以4字节对齐的方式来读取或写入内存,那么同样这4个字节的数据是以什么顺序保存在
内存中的呢?这就是所谓的字节序的问题了
每个数据都有“有效位”的概念,意思是“表示这个数据所用的字节”。例如一个32位整数,它的有效位就是4个字节。
举个例子,对于0x11223344来说,它的有效位从高到低便是11、22、33、44
对大字节序(big endian)(大端)来说,“最高有效位”落在低地址上
对小字节序(little endian)(小端)来说就是相反的方式,它把“最低有效位”放在低地址上
常用的CPU架构,如Intel,AMD的CPU使用的都是小字节序
那问题来了,我们如何对系统时大字节序还是小字节序进行检查呢?
第一种方法,使用强制类型转换的方式。C 语言在把占用2个字节的 short 变量强制转换为 char 之后,会把 short 变量的首地址赋给 char 变量,可以根据 char 变量的值判断系统字节序是 大端 还是 小端。
第二种方法,利用 联合类型 的特性。联合类型 共享同一段内存,首地址是相同的。
/******************* * 文件名:endian.c ******************/ #include <stdio.h> /********************************************************* * 使用类型的强制转换实现little-endian与big-endian的判断 ********************************************************* * 返回值: * 1 表示是小端字节序。 * 0 表示不是小端字节序。 *********************************************************/ int is_little_endian_a(void) { unsigned short flag = 0x4321; if(*(unsigned char*)&flag == 0x21) return 1; else return 0; } /********************************************************************************* * 利用联合的特点来判断little-endian与big-endian ********************************************************************************* * 返回值: * 1 表示是小端字节序。 * 0 表示是大端字节序。 * -1 表示不能使用这种方法确定字节序。比如有的机器的 short 长度不是 2 。 ********************************************************************************/ int is_little_endian_b(void) { union endian_un{ short var; char bits[sizeof(short)]; }; union endian_un flag; flag.var=0x0102; //判断低位和高位的存储内容,确定是何种方式 if(sizeof(short) == 2){ if(flag.bits[0] == 1 && flag.bits[1] == 2) return 0; else if(flag.bits[0] == 2 && flag.bits[1] == 1) return 1; else return -1; } return -1; } int main(void) { int type = 0; type = is_little_endian_a(); if (1 == type) printf("judged by first method, little-endian\n"); else if (0 == type) printf("judged by first method, big-endian\n"); type = is_little_endian_b(); if (1 == type) printf("judged by second method, little-endian\n"); else if (0 == type) printf("judged by second method, big-endian\n"); else printf("can‘t judge it\n"); return 0; }
Mac平台上面进行测试,效果如下:
adeMacBook-Pro:lua_dev apple$ ./endian judged by first method, little-endian judged by second method, little-endian
应用:
主要在多台计算机之间数据的传递上面,如何去编排字节顺序,多用于分布式网络系统的设计上面;