本篇將以what,why,how三個維度講述字節序
what
字節序,字面理解可知是字節(Byte)的順序,是計算機科學針對多字節結構(變量或者文件等)的一種約定,目前分爲大端字節序和小端字節序
以一個 uint32_t 的4字節類型爲例,在該類型的變量中存入0x12345678,從變量的角度來看,0x12爲變量的高字節,0x78爲變量的低字節。
當變量的 高 字節存放在內存的 高 地址,變量的 低 字節存放在內存的 低 地址時,爲小端字節序,如下圖:
當變量的 高 字節存放在內存的 低 地址,變量的 低 字節存放在內存的 高 地址時,爲大端字節序,如下圖:
why
定義只是約定,當然可以直接記憶,但是爲什麼要這麼約定?爲什麼要分成兩種字節序?有什麼好處?
兩種字節序針對兩類對象,大端字節序 面向的是 人類,小端字節序 面向的是 計算機。
大端字節序符合人類閱讀的習慣,對字節流的處理也是按照閱讀習慣來定義,這樣能減少人類的處理負擔,因此如網絡字節序用的就是大端字節序,當網絡socket傳輸一個多位數時,按照閱讀習慣,接收到的是高字節數,因此直接左移8位相加。
小端字節序符合計算機處理的順序
1.計算機讀取數據不關心格式,僅按照內存地址順序讀取
2.計算機處理數據從數據低位開始處理,這個也是計算機設計定義的,因此我們需要把變量低地址的數據主動放到內存低地址處,這樣計算機取到數據處理纔是我們所期望的從低地址開始。如累加操作時,個位相加,進位置位CF,再做十位相加,依次進行累加最終得到結果。
綜上,大端字節序面向人類爲了簡化思維,小端字節序面向計算機爲了加快處理速度。
how
如何判別計算機是大端字節序還是小端字節序?
可以簡單的用一段C語言程序做判斷
#include <cstdio>
#include <cstdint>
int main()
{
uint32_t test_code = 0x12345678;
uint8_t* first = (uint8_t*)&test_code; //指針指向變量的內存首字節
printf("first address value is %x,is %s\n",
*first, *first == 0x12 ? "Big Endian" : "Little Endian");
return 0;
}
可以看到輸出爲
first指針指向了變量test_code的內存首地址(內存低地址),取出的結果爲0x78(變量低地址),由上文定義可知爲小端序
除了直接查看輸出,我們還能通過查看內存方式自己看看存儲的情況,這裏使用ollyDbg調試上述程序debug模式輸出的exe文件,使用ollyDbg打開該exe文件:
右鍵搜索程序中所有的字符串,這裏主要要找printf中的字符串,因爲是簡單程序沒有加密,很容易能夠找到調用的地方:
直接查看該變量地址的dump
與程序輸出一直,低地址存放着0x78,高地址存放着0x12,因此爲小端序。