老青菜

字节顺序

2019-01-21

字节顺序,又称端序或尾序(Endianness),是指存储器中或在数字通信链路中,组成多字节的排列顺序。

而在计算机系统中,我们是以字节为单位的,一个字节(byte)占8bit。不同的数据类型,占用的字节数也各不相同。

c语言中,常用类型占用字节数(byte)如下:

类型 32位 64位
char 1 1
short int 2 2
int 4 4
long int 4 8
long long int 8 8
char* 4 8
float 4 4
double 8 8

前言

例如,我们声明一个变量:

int a = 305419896;//等同于0x12345678(16进制)
printf("&a : %p\n", &a);//打印地址

//或者 lldb debug模式下,执行命令
po &a

打印地址,得到0x7ffeefbff5fcprintf省略了高位0x0000)。那么0x12345678这四个字节如何存储呢?

0x7ffeefbff5ac 0x7ffeefbff5ad 0x7ffeefbff5ae 0x7ffeefbff5af
0x? 0x? 0x? 0x?

这样就引入了两种不同的存储顺序:大端序列、小端序列。

  • x86架构的系统(windowsFreeBSDLinux)使用的是小端模式。
  • Mac OS是大端模式(序列)。
  • TCP/IP协议规定了在网络上字节传输采用是大端模式。

那么什么是大端模式(序列),小端模式(序列)?

大端序列

big-endian,又称大尾序,即高位字节排放在内存的低地址端(该值的起始地址),低位字节排放在内存的高地址端。
如何理解呢?我们还是接着上面的例子:

int a = 305419896;//等同于0x12345678(16进制)
printf("&a : %p\n", &a);

//或者 lldb debug模式下,执行命令
po &a

得到地址是0x00007ffeefbff5ac,接着我们来看一下a地址的内存布局,debug模式下,选择view memory,如图:
 

 
内存布局如下:

 
我们可以很清晰的看到,a的高位字节0x78存放在低地址,地为字节0x12存放在高地址上,这就是大端序列。

0x7ffeefbff5ac 0x7ffeefbff5ad 0x7ffeefbff5ae 0x7ffeefbff5af
0x78 0x56 0x34 0x12


小端序列

little-endian,又称小尾序,低位字节排放在内存的低地址端(该值的起始地址),高位字节排放在内存的高地址端。
接着上面的例子,小端序列的字节存储结果:

0x7ffeefbff5ac 0x7ffeefbff5ad 0x7ffeefbff5ae 0x7ffeefbff5af
0x12 0x34 0x56 0x78


大小端序的判断

理解了大小端序的特性,我们可以通过低地址的字节来判断了。

#include <stdio.h>

int main(int argc, char *argv[])
{
    int a = 305419896;//等同于0x12345678(16进制)
    char *p = (char*)&a;
    if(p[0] == 0x78) {
        printf("big endian\n");
    }
    else {
        printf("little endian\n");
    }
}

mac os下输出结果:

big endian


参考链接

wikipedia - 字节顺序

使用支付宝打赏
使用微信打赏

若你觉得我的文章对你有帮助,欢迎点击上方按钮对我打赏

扫描二维码,分享此文章