大小端为什么存在
没有规范,所以就有了;毕竟都是人创造出来的~,你这样,我就那样
大小端的原理
Endian表示数据在存储器中的存放顺序
-
大端:(Big-Endian):指数据的高字节保存在内存的低地址中,而数据的低字节保存在内存的高地址中。
-
小端:(Little-Endian):指数据的高字节保存在内存的高地址中,而数据的低字节保存在内存的低地址中。
不管是大端法还是小端法存储,计算机在内存中存放数据的顺序都是从低地址到高地址,所不同的是首先取低字节的数据存放在低地址还是取高字节数据存放在低地址。
大端法和小端法指的是字节在内存中存储时的排列规则,而不是数据中的位的排列规则。也有以位序排列的机器,但很少见。另外,再次明确一下,大端法或小端法是数据在存储时的表现,而不是在寄存器中参与运算时的表现。
图文并茂
如int a=0x01020304,把它赋值到一个数组内b[4];
(惯性思维,04是最小的,也就是赋值b[0]=0x04,以此类推,这就是小端;在操作系统中,x86和一般的OS(如windows,FreeBSD,Linux)使用的是小端模式。但比如Mac OS是大端模式。)
0x01020304 | ||||
---|---|---|---|---|
b[4] | 0 | 1 | 2 | 3 |
大端 | 01 | 02 | 03 | 04 |
小端 | 04 | 03 | 02 | 01 |
代码测试
#include <stdio.h>
typedef union
{
int a;
char b[4];
}uEndian;
int main(void)
{
uEndian p;
p.a = 1;//0x00 00 00 01
if (p.b[0] == 1)
printf("第一个字节为1,小端存储\n");
else
printf("第一个字节为0,大端存储\n");
return 0;
}
不用联合体的测试代码
int main(void)
{
int a = 0x1234;
//通过将int强制类型转换成char单字节,通过判断起始存储位置。即等于 取b等于a的低地址部分
char b = *(char *)&a;
if (b == 0x34)
printf("第一个字节为34,小端存储\n");
else
printf("第一个字节为0,大端存储\n");
return 0;
}
通讯协议
- 网络字节序:TCP/IP协议传输数据时,字节序默认大端。
以下以主机为小端模式,给出相应的转换代码;如果为大端模式,不需要转换
#define ntohs(n) //16位数据类型网络字节顺序到主机字节顺序的转换
#define htons(n) //16位数据类型主机字节顺序到网络字节顺序的转换
#ifndef _swap16
#define _swap16(n) \
((((n) & 0xff) << 8) | (((n) & 0xff00) >> 8))
#endif
#ifndef htons
#define htons(s) _swap16(s)
#endif
#ifndef ntohs
#define ntohs(s) _swap16(s)
#endif
#define ntohl(n) //32位数据类型网络字节顺序到主机字节顺序的转换
#define htonl(n) //32位数据类型主机字节顺序到网络字节顺序的转换
#ifndef _swap32
#define _swap32(n) \
((((n) & 0xff) << 24) | (((n) & 0xff00) << 8) | (((n) & 0xff0000UL) >> 8) | (((n) & 0xff000000UL) >> 24))
#endif
#ifndef htonl
#define htonl(l) _swap32(l)
#endif
#ifndef ntohl
#define ntohl(l) _swap32(l)
#endif