2012-08-28 246 views
4

我看到一個辦法知道平臺的字節順序是這樣的程序,但我不明白它如何解釋*((的char *)&A)

#include <stdio.h> 
int main(void) 
{ 
    int a = 1; 
    if(*((char*)&a) == 1) printf("Little Endian\n"); 
    else printf("Big Endian\n"); 
    system("PAUSE"); 
    return 0; 
} 

是什麼測試呢?

+1

可能重複[在C++程序中以編程方式檢測字節順序](http://stackoverflow.com/questions/1001307/detecting-endianness-programmatically-in-ac-program) –

+2

@DonalFellows不確定在dup上,這個問題已經找到代碼並想知道它是如何工作的。潛在的dup只是詢問如何檢測字節序的一般問題。 –

+1

可能的重複[小vs大永恆:如何解釋測試](http://stackoverflow.com/questions/9971369/little-vs-big-endianess-how-to-interpret-the-test) –

回答

9

int幾乎總是大於一個字節,並且經常跟蹤體系結構的字大小。例如,一個32位體系結構可能會有32位整數。因此,考慮典型的32位整數,4個字節的佈局可能是:

00000000 00000000 00000000 00000001 

或用最少的顯著字節第一:

00000001 00000000 00000000 00000000 

一個char *是一個字節,所以如果我們投這個地址爲char *我們將得到上面的第一個字節,無論是

00000000 

00000001 

所以通過檢查第一個字節,我們可以確定架構的字節順序。

+1

在64位Linux上,'int'是32位的。 –

+0

@JamesMcLaughlin我不知道,謝謝。我軟化了語言。 –

2
  1. 採取的a
  2. 投它char*
  3. 地址解引用這個char*,這會給你的int
  4. 第一字節檢查它的價值 - 如果它是1,那麼它的小端。否則 - 大。

假設sizeof(int) == 4,則:

|........||........||........||........| <- 4bytes, 8 bits each for the int a 
| byte#1 || byte#2 || byte#3 || byte#4 | 

當步驟1,2和3被執行時,*((char*)&a)會給你的第一個字節,| byte#1 |

然後,通過檢查byte#1的值,您可以瞭解它是大還是小的。

1

該方案只是重新解釋由int所佔用的空間作爲char秒的陣列,並假設1作爲int將被存儲爲一系列字節,最低階這些都將是有價值的1字節,其餘爲0.

所以如果最低位字節先出現,那麼平臺就是小端,否則它的大端。

這些假設可能不適用於存在的每個單一平臺。

4

這隻適用於sizeof(int) > 1的平臺。作爲一個例子,我們假設它是2,並且char是8位。

基本上,小端,作爲一個16位的整數數字1是這樣的:

00000001 00000000 

但隨着大端,它是:

00000000 00000001 

所以第一代碼集a = 1,然後將此:

*((char*)&a) == 1) 

需要的a地址,將其視爲AP請參閱char,並將其解除引用。所以:

  • 如果a包含一個小端整數,你將得到00000001部分,當作爲char

  • 如果a包含大端整數interpeted爲1,相反,您將獲得00000000== 1的檢查將失敗,並且代碼將假定該平臺是big-endian。

您可以通過使用int16_tint8_t代替intchar改善此代碼。或者更好,只需檢查htons(1) != 1

+0

關於sizeof(int)的+1好處> 1 –

+0

C89 2.2.4.2和C99 5.2.4.2.1要求'sizeof(int)> 1',要求'INT_MIN'和'INT_MAX'的值超過'char'的容量,所以當你的警告是真實的時候,它是真實的。更有意思的是,這段代碼在不是大端或小端的中端系統上會不正確地工作。 (雖然這樣的系統的頻率足夠小,如果你不得不問他們是什麼,你可能不需要關心他們。:-)) –

2
  • 您可以將整數視爲4字節的數組(在大多數平臺上)。小尾數整數將具有值01 00 00 00和大尾數00 00 00 01
  • 通過做&a你得到該數組的第一個元素的地址。
  • 表達式(char*)&a將其轉換爲單個字節的地址。
  • 最後*((char*)&a)獲取該地址所包含的值。
1
a = 00000000 00000000 00000000 00000001 
    ^        ^
    |         | 
    &a if big endian     &a if little endian 

    00000000     00000001 
    ^        ^
    |         | 
    (char*)&a for BE     (char*)&a for LE 

    *(char*)&a = 0 for BE    *(char*)&a = 1 for LE 
+0

+1爲好的ASCII藝術。 –

+0

只要知道這個漂亮的圖形翻轉排序的感覺:它移動計算的指針指向的地方,而不是重新排序整數的字節。 – quamrana

0
*((char*)&a) 

在用於INT I = 1(大小爲4字節)大尾端的數據將在存儲器中作爲安排: - (從低地址向高地址)。

00000000 -->Address 0x100 
00000000 -->Address 0x101 
00000000 -->Address 0x102 
00000001 -->Address 0x103 

雖然LittleEndian是: -

00000001 -->Address 0x100 
00000000 -->Address 0x101 
00000000 -->Address 0x102 
00000000 -->Address 0x103 

判斷上面鑄: -

另外&a= 0x100因此
*((char*)0x100)意味着考慮通過取一個字節(因爲4個字節加載INT)一段時間以便引用0x100處的數據。

*((char*)&a) == 1 => (*0x100 ==1) that is 1==1 and so true,implying its little endian. 
+0

您似乎翻轉了一個字節中的位順序以及int中的字節順序! – quamrana

+0

非常非常感謝,我也許按了一個主頁按鈕而不是結束:) – perilbrain

1

下面是它的分解:

  a  -- given the variable a 
      &a  -- take its address; type of the expression is int * 
    (char *)&a  -- cast the pointer expression from type int * to type char * 
*((char *)&a)  -- dereference the pointer expression 
*((char *)&a) == 1 -- and compare it to 1 

基本上,鑄造(char *)&a表達&a的從一個指針的類型轉換爲int的指針char;當我們將解引用運算符應用於結果時,它會給我們存儲在a的第一個字節中的值。