大小端問題

什么是大小端?

大端模式,是指數(shù)據(jù)的高字節(jié)保存在內(nèi)存的低地址中,而數(shù)據(jù)的低字節(jié)保存在內(nèi)存的高地址中,這樣的存儲模式有點兒類似于把數(shù)據(jù)當作字符串順序處理:地址由小向大增加,而數(shù)據(jù)從高位往低位放;這和我們的閱讀習慣一致。

小端模式,是指數(shù)據(jù)的高字節(jié)保存在內(nèi)存的高地址中,而數(shù)據(jù)的低字節(jié)保存在內(nèi)存的低地址中,這種存儲模式將地址的高低和數(shù)據(jù)位權(quán)有效地結(jié)合起來,高地址部分權(quán)值高,低地址部分權(quán)值低。

要注意一點,也就是,這里的高字節(jié)和低字節(jié)與高地址和低地址是兩個截然不同的概念。習慣上,將一個數(shù)字按位寫到紙上時,我們會從左至右,從高位到低位一位一位地寫,這是一種具體的行為。在談到一個多字節(jié)整型數(shù)據(jù)的高低字節(jié)時,我們并沒有考慮它如何進行存儲,而是按照人類的習慣,將權(quán)值高的字節(jié)稱作高字節(jié),權(quán)值地的稱作低字節(jié)。

大小端模式的判斷

Linux 源碼中判斷大小端模式的方法

static union {
    int i;
    char c[4];
} endian_test = {{'l', '?', '?', 'b'}};

#define ENDIANNESS ((char)endian_test.i)

理解上面的代碼的關(guān)鍵是,

int -> char 的轉(zhuǎn)換要截斷到int的最后一個字節(jié)(只保留低8位)。
字符串不用考慮大小端模式的問題,從左至右內(nèi)存地址依次增高

+---+---+---+---+
| l | ? | ? | b +
+---+---+---+---+
  • 如果是小端模式,那么低字節(jié)保留在低地址,而這里如果按char來尋址,低地址也即是最左邊的那個字節(jié),其中存儲了'l'

  • 如果是大端模式,那么低字節(jié)保留在高地址,而這里如果按char來尋址,高地址也即是最右邊的那個字節(jié),其中存儲了'b'

什么時候需要判斷大小端模式?
一般情況下,只有需要跟硬件直接打交道的地方才需要自己去判斷大小端,其余的地方編譯器和操作系統(tǒng)會幫你搞定,比如對多字節(jié)數(shù)據(jù)類型進行按位運算。另外,網(wǎng)絡傳輸數(shù)據(jù)的時候是按照字節(jié)傳輸?shù)?,這時候就需要考慮字節(jié)序。

一個簡單的例子

#include <stdio.h>
#include <stdlib.h>

static union {
    int i;
    char c[4];
} endian_test = {{'l', '?', '?', 'b'}};

#define ENDIANNESS ((char)endian_test.i)


void printbyte(char byte)
{
    for (int i = 0; i < 8; ++i)
        putchar('0' + ((byte >> (7 - i)) & 0x1));
}

// 從高字節(jié)到低字節(jié),高位到低位
void print_int4b(int x)
{
    const char *s = (char *)&x;
    if (ENDIANNESS == 'l') {
        for (int i = 3; i >= 0; --i)
            printbyte(s[i]);
    }
    else if (ENDIANNESS == 'b') {
        for (int i = 0; i <= 3; ++i)
            printbyte(s[i]);
    }
    else {
        fprintf(stderr, "%s\n", "unknown endianness");
        exit(1);
    }
    putchar('\n');
}

void print_int32(int x)
{
    for (int i = 0; i < 32; ++i)
        putchar('0' + ((x >> (31 - i)) & 0x1));
    putchar('\n');
}


int main()
{
    int i = 100;
    print_int4b(i);
    print_int32(i);

    return 0;
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關(guān)閱讀更多精彩內(nèi)容

  • 1、大小端問題的由來 在計算機內(nèi)存中,通常是以字節(jié)(Byte),也就是 8 個位(Bit)為基本存儲單元(也有以 ...
    姚興泉閱讀 2,876評論 0 3
  • 一、定義 大端模式:大端模式就是指把數(shù)據(jù)的高字節(jié)保存在內(nèi)存的低地址中,數(shù)據(jù)的低字節(jié)保存在內(nèi)存的高地址中,這和我們一...
    rmrfany閱讀 1,494評論 0 2
  • 在幾乎所有的機器上,多字節(jié)對象都被存儲為連續(xù)的字節(jié)序列。例如在C語言中,一個類型為int的變量x地址為0x100,...
    JumpDong閱讀 1,341評論 0 0
  • 如果將一個32位的整數(shù)0x12345678存放到一個整型變量(int)中,這個整型變量采用大端或者小端模式在內(nèi)存中...
    hailiu13閱讀 785評論 0 0
  • __block和__weak修飾符的區(qū)別其實是挺明顯的:1.__block不管是ARC還是MRC模式下都可以使用,...
    LZM輪回閱讀 3,592評論 0 6

友情鏈接更多精彩內(nèi)容