天天看點

C中的位域與大小端問題

端模式分為:大端位元組序和小端位元組序,也就是位元組在記憶體中的順序。

記憶體中位址存放資料的順序是:由低到高。

大端位元組序:高位元組存于記憶體低位址,低位元組存于記憶體高位址。如一個long型資料0x12345678

記憶體低位址--> 0x12

    .  0x34

    .  0x56

記憶體高位址--> 0x78

小端位元組序:低位元組存于記憶體低位址,高位元組存于記憶體高位址。

記憶體低位址--> 0x78           

               .     0x56

               .     0x34

記憶體高位址--> 0x12

位元組的大端序還是小端序是由CPU決定的。

我們常用的X86結構是小端模 式,而KEIL C51則為大端模式。很多的ARM,DSP都為小端模式。有些ARM處理器還可以由硬體來選擇是大端模式還是小端模式。

在VC中的實驗如下:

int  temp = 0x12345678;

  調試中,該變量在記憶體中的表現形式是78 56 34 12,但其真實的數值還是0x12345678,隻不過記憶體中表現的位元組順序與我們所認為的位元組順序剛好是反着的,同時也說明我的PC是遵循大端位元組序的。

=========================================================

需要考慮大小端(位元組順序)的情況?

1、所寫的程式需要向不同的硬體平台遷移,說不定哪一個平台是大端還是小端,為了保證可移植性,一定提前考慮好。

2. 在不同類型的機器之間通過網絡傳送二進制資料時。 一個常見的問題是當小端法機器産生的資料被發送到大端法機器或者反之時,接受程式會發現,字(word)裡的位元組(byte)成了反序的。為了避免這類問 題,網絡應用程式的代碼編寫必須遵守已建立的關于位元組順序的規則,以確定發送方機器将它的内部表示轉換成網絡标準,而接受方機器則将網絡标準轉換為它的内部标準。

3. 當閱讀表示整數的位元組序列時。這通常發生在檢查機器級程式時,e.g.:反彙編得到的一條指令:

80483bd: 01 05 64 94 04 08        add �x, 0x8049464

3. 當編寫強轉的類型系統的程式時。

例1:如寫入的資料為u32型,但是讀取的時候卻是char型的:

如:0x1234, 大端讀取為12時,小端獨到的是34。

例2:将buffer中的數轉換為整型:

如:int src = 0x1234

       memcpy(buffer, src, sizeof(int));

      大端:buffer[4] = {0x01, 0x02, 0x03, 0x04};

      小端:buffer[4] = {0x04, 0x03, 0x02, 0x01};

提高程式的可移植性

使用宏編譯

#ifdef LITTLE_ENDIAN

//小端的代碼

#else

//大端的代碼

#endif

大、小端之間的轉換代碼

1、小端轉換為大端

#include <stdio.h>

void show_byte(char *addr, int len)

{

       int i;

       for (i = 0; i < len; i++)

       {

              printf("%.2x \t", addr[i]);

       }

       printf("\n");

}

int endian_convert(int t)

{

       int result;

       int i;

       result = 0;

       for (i = 0; i < sizeof(t); i++)

       {

              result <<= 8;

              result |= (t & 0xFF);

              t >>= 8;

       }

       return result;

}

int main(void)

{

       int i;

       int ret;

       i = 0x1234567;

       show_byte((char *)&i, sizeof(int));

       ret = endian_convert(i);

       show_byte((char *)&ret, sizeof(int));

       return 0;

}