大小端爲什麼存在
沒有規範,所以就有了;畢竟都是人創造出來的~,你這樣,我就那樣
大小端的原理
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