1、字节序
1.1、大端字节序(big-endian)
数据低位存储在高地址位,数据高位存储在低地址位。
假设定义一个变量并赋予初值:
int a = 0x12345678;
对于这个整型数据,一共有四个字节,假设为其分配的地址空间为0x1001~0x1004,则从低位到高位,每个字节依次是:12、34、56、78。数据将会以下面的形式储存在内存中:
1.2、小端字节序(little-endian)
数据低位存储在低地址位,数据高位存储在高地址位。
假设定义一个变量并赋予初值:
int a = 0x12345678;
对于这个整型数据,一共有四个字节,假设为其分配的地址空间为0x1001~0x1004,则从低位到高位,每个字节依次是:78、56、34、12。数据将会以下面的形式储存在内存中:
2、验证大端字节序还是小端字节序
2.1、通过联合体union判断
联合体是一个能在同一存储空间存储不同类型的数据类型。简单来讲,这段地址空间是联合体中各成员变量共用的,具体用到多少空间取决于各成员变量自身的大小。但是,一个联合体的大小取决于联合体成员中最大的变量的大小。
定义一个联合体:
union u_data
{
unsigned char a;
unsigned int b;
} data;
在这个联合体中,共用的是低地址位的一个字节,如果需要获取b的值,那么就需要根据系统其对应的大小端字节序来取4个字节的值,而获取a的值,系统只会从该段地址中的低地址取1个字节的值。
所以,通过给b赋值,然后再获取a的值,即可根据结果判断系统是大端字节序还是小端字节序。
根据上面的图示,如果构建联合体u_data,并将b赋初值0x12345678,如果读取a的值为0x78,则代表系统是小端字节序,如果读取a的值为0x12,则代表系统是大端字节序。
代码验证:
#include <stdio.h> int main()
{ union u_data { unsigned char a; unsigned int b; } data; data.b = 0x12345678; if (data.a = 0x78) { printf("小端字节序\n"); } else if (data.a == 0x12) { printf("大端字节序\n"); } return 0;
}
2.2、通过指针判断
先用代码实现,然后再分析实现原理:
#include <stdio.h> int main()
{ int a = 0x12345678; char *p = NULL; p = (char *)&a; if (*p == 0x78) { printf("小端字节序\n"); } else if (*p == 0x12) { printf("大端字节序\n"); } return 0;
}
代码中定义了一个整型变量a,char型指针变量p。指针会指向整型数的首地址,当调用p往地址里取值时,系统会根据指针的类型大小去对应大小的值。
例如,程序中char型的指针就会从它指向的地址往后取char类型(1个字节)的值,故首先会取其低地址位的1个字节的内容。如果p=0x78,可以判断系统是小端字节序;如果p=0x12,可以判断系统是大端字节序。