大端字节序(big-endian)是一种将数据高有效位存放在低内存地址的方式,而数据低有效位存放在高内存地址。
如图是大端机多字节字节序:
如果是带位域的话,比如一个占一字节的结构体:
struct S{
unsigned char x1 : 2,
x2 : 6;
};
struct S s = {s.x1 = 0x0, s.x2 = 0xA };
对于大端机,S的两个位域成员x1和x2都位于内存A所对应的一个字节,并且x1位于该字节的高2比特位,x2位于低6比特位。
对于大端机结构体中位域成员定义的顺序,就是内存中该地址字节中位域的实际存放顺序。
如图,大端机位域的字节序:
小端字节序:是一种将数据低有效位存放在低内存地址的方式,而数据高有效位存放于高内存地址。
图和上面的大端字节序的图是相反的,这里省略。
判断大端还是小端:
#include <stdio.h>
int main(){
union{
int n;
char ch;
} data;
data.n = 0x00000001; //也可以直接写作 data.n = 1;
if(data.ch == 1){
printf("Little-endian\n");
}
else{
printf("Big-endian\n");
}
return 0;
}
共用体的各个成员是共用一段内存的。1 是数据的低位,如果 1 被存储在 data 的低字节,就是小端模式,这个时候 data.ch 的值也是 1。如果 1 被存储在 data 的高字节,就是大端模式,这个时候 data.ch 的值就是 0。
位域的字节序:
#include<stdio.h>
#include<stdlib.h>
struct S{
unsigned char x1 : 2,
x2 : 6;
};
int main()
{
unsigned char var;
struct S *p;
struct S s = {s.x1 = 0x0, s.x2 = 0xA };
p = &s;
printf("s.x1 = 0x%x\n", s.x1);
printf("s.x2 = 0x%x\n", s.x2);
printf("s = 0x%x\n", *(char*)p);
var = *(char*)p >> 2;
printf("v = 0x%x\n", var);
return 0;
}
结果也是满足小端字节序。00 001010在内存中是001010 00,所以是0x28