C語言中數據是存儲在內存中的,而內存空間又被劃分爲以字節爲單位的連續地址空間,那麼,我們定義的變量是在內存中如何存儲的呢。我們把變量在內存中的存儲分爲兩種,大端字節序存儲與小端字節序存儲。
網絡字節序都是大端字節序
主機字節序看本身電腦的情況,有可能是大端有可能是小端
1.大小端的概念
大小端字節序的概念其實非常簡單,小端字節序無非就是高地址高內存,低地址低內存。大端字節序就是反過來,高地址低內存,低地址高內存。數據的低字節存儲在低地址處,高字節存儲在高地址處。數據的低字節存儲在高地址處,高字節存儲在低地址處。
2.爲什麼有大小端之分
在計算機系統中,我們是以字節爲單位的,每個地址單元都對應着⼀個字節,⼀個字節爲8bit。然而在C語言中了8bit的char之外,還有 16bit(2字節)的short型, 32bit(4字節)的long型、int型(要看具體的編譯器)。另外,對於位數⼤於8位的處理 器,例如16位或者32位的處理器,由於寄存器寬度⼤於⼀個字節,那麼必然存在着⼀個如何將多個字節安排的問題。由此大端和小端就出現了。
比如:⼀個16bit的 short型w,它的值爲0x1122,那麼它的高字節爲0x11,低字節爲0x22。它在內存中的地址爲0x0010。
如果爲大端字節序:高字節0x11就存放在低地址0x0010中,低字節0x22就要存放在比0x0010高的地址0x0011中。小端則相反。
3.相關函數
htonl ntohl htons ntohs
h代表host,主機字節序 n代表net,網絡字節序
這幾個函數用到的頭文件
#include <arpa/inet.h>
3.1htonl()函數
函數原型:uint32_t htonl(uint32_t hostlong)
- hostlong是主機字節順序表達的32位數,htonl中的h–host主機地址,to–to,n–net網絡,l–unsigned long無符號的長整型(32位的系統是4字節);
- 函數返回值是一個32位的網絡字節順序;
- 函數的作用是將一個32位數從主機字節順序轉換成網絡字節順序。
3.2htons()函數
函數原型:uint16_t htons(uint16_t hostlong)
- hostlong是主機字節順序表達的16位數,htons中的h–host主機地址,to–to,n–net網絡,s–signed long無符號的短整型(32位的系統是2字節);
- 函數返回值是一個16位的網絡字節順序;
- 函數的作用是將一個16位數從主機字節順序轉換成網絡字節順序,簡單的說就是把一個16位數高低位互換。
3.3ntohs()函數
函數原型:uint16_t ntohs(uint16_t hostlong)
- hostlong是網絡字節順序表達的16位數,ntohs中的,n–net網絡,to–toh–host主機地址,s–signed long有符號的短整型(32位的系統是2字節);
- 函數返回值是一個16位的主機字節順序;
- 函數的作用是將一個16位數由網絡字節順序轉換爲主機字節順序,簡單的說就是把一個16位數高低位互換。
3.4ntohl()函數
函數原型:uint32_t ntohs(uint32_t hostlong)
- hostlong是網絡字節順序表達的32位數,ntohs中的,n–net網絡,to–toh–host主機地址,s–unsigned long無符號的短整型(32位的系統是4字節);
- 函數返回值是一個32位的主機字節順序;
- 函數的作用是將一個32位數由網絡字節順序轉換爲主機字節順序。
4.判斷大小端存儲方式
我們來設計一個程序看看自己電腦的主機字節序是大端還是小端
#include<stdio.h>
#include <arpa/inet.h>
int check_sys();
int check_sys1();
int main(int argc, char **argv)
{
int a = 1;
int rv;
//這裏可以選用兩種方法來判斷
rv = check_sys();
//rv = check_sys1();
if(rv == 1)
{
printf("samll\n");
}
else if(rv == 0)
{
printf("big\n");
}
return 0;
}
int check_sys()
{
int a = 1;
return *(char *)&a;
}
int check_sys1()
{
union un
{
char c;
int i;
}u;
u.i = 1;
return u.c;
}
運行結果:
我的電腦是small!