乐趣区

大小端

大小端
一般人的书写习惯:数据左边的为高位,右边的为低位,地址则相反:地址左边的为低位,右边的为高位例如数据 16 位数据:0x12345678,12 为数据的高位,78 位数据的低位

大端模式,是指数据的高字节保存在内存的低地址中,而数据的低字节保存在内存的高地址中,这样的存储模式有点儿类似于把数据当作字符串顺序处理:地址由小向大增加,而数据从高位往低位放;这和我们的阅读习惯一致。
例如四字节的数据:0x12345678,地址低 -> 高,低地址存放高位,高地址存放位,存储为:

12
34
56
78

小端模式,是指数据的高字节保存在内存的高地址中,而数据的低字节保存在内存的低地址中,这种存储模式将地址的高低和数据位权有效地结合起来,高地址部分权值高,低地址部分权值低。
例如四字节的数据 0x12345678,地址:低 -> 高,高地址存放高位,低地址存放低位,存储为:

78
56
34
12

只需记住与我们阅读习惯一致的为大端模式。
判断方法

union 方法

union 的特殊性会申请内部最大的长度为 union 的长度,取值会从地址的开始往后读取
#include <stdio.h>
union check_point{
int a;
char b;
} check_point;
int main()
{
check_point.a=1;
if(check_point.b == 1)
printf(“LITTLE ENDIAN!\n”);
else
printf(“BIG ENDIAN !\n”);
return 0;
}
我的测试机为 mac,为小端模式,所以执行结果是
LITTLE ENDIAN!
linux 内核也是用了类似的方法:
tatic union {char c[4]; unsigned long mylong; } endian_test = {{‘l’, ‘?’, ‘?’, ‘b’} };
#define ENDIANNESS ((char)endian_test.mylong)
测试用例如下:
#include <stdio.h>
static union {char c[4]; unsigned long mylong; } endian_test = {{‘l’, ‘?’, ‘?’, ‘b’} };
#define ENDIANNESS ((char)endian_test.mylong)
int main()
{
printf(“%c \n”,ENDIANNESS);
return 0;
}
测试结果:
l
linux 内核可直接使用 ENDIANNESS 宏的返回结果判断大小端

int 1 的特殊性

int 1 的大端存储方式为地址:低 -> 高,高地址存放低位,低地址存放高位

00
00
00
01

小端存储方式为地址:低 -> 高,高地址存放高位,低地址存放低位

01
00
00
00

#include <stdio.h>
int main()
{
int a = 1;
char pc = *(char*)(&a);
if (pc == 1)
printf(“LITTLE\n”);
else
printf(“BIG\n”);

return 0;
}
输出结果为:
LITTLE

退出移动版