2011-04-12 36 views
4

對於特定需要我建立一個四個字節整數出四個一字節字符,使用沒有什麼太特別的(在我的小端平臺):在big-endian機器中對little-endian整數進行簡單的按位操作?

return ((v1 << 24) | (v2 << 16) | (v3 << 8) | v4); 

我知道,存儲在大端整數機器看起來像AB BC CD DE,而不是DE CD BC AB的小端排列,雖然它會影響我的操作完全是因爲我將錯誤地移位,還是隻會導致正確的結果存儲在相反的位置,並且需要顛倒?

我想知道是否要創建此函數的第二個版本來處理大端機器的位操作,或者可能使用與ntonl相關的函數,但我不清楚如何知道我的編號是否正確。

你會有什麼建議來確保兼容性,牢記我需要以這種方式形成整數?

回答

8

只要你在的水平上工作,無論你的機器是小端還是大端,你獲得的結果都是完全沒有區別的。即只要您使用的是語言級別的運算符(例如,在您的示例中爲|<<),則在任何平臺上您都將得到與上述表達式完全相同的算術結果。機器的排列順序不可檢測,並且在此級別不可見。

當您需要關心字節序的唯一情況是當您正在使用的數據在對象表示級別檢查時,即在其原始內存表示很重要的情況下。你上面說的關於「AB BC CD DE而不是DE CD BC AB」的內容特別是關於數據的原始存儲器佈局。這就是ntonl這樣的功能:它們將一個內存佈局轉換爲另一個內存佈局。到目前爲止,您沒有指出實際的原始內存佈局對您來說很重要。是嗎?同樣,如果您只關心上述表達式的,那麼它完全和完全獨立於字節序。基本上,當你編寫不試圖訪問和檢查原始內存內容的C程序時,你根本不應該關心字節碼。

+0

這證實了我原先曾經想過的事情,因爲這種轉換可能是多餘的,因爲它還沒有存儲。謝謝。 – Alexander 2011-04-13 00:08:21

+1

其原因是因爲寄存器通常不被認爲是一種排序或另一種排序。幾乎所有的(全部?)體系結構,甚至是像x86這樣的小端形式的體系結構都使得寄存器的最左邊的位成爲MSB,最右邊的LSB(右邊和左邊被定義爲方向位左移或右移)。 – user470379 2011-04-13 00:17:53

+0

我非常感謝你對你的意見。這回答了我需要知道的關於這個主題的所有內容,甚至在編寫這些功能時甚至不用關心什麼。 – Alexander 2011-04-13 00:32:06

1

[改寫爲清楚起見]

ntohl(和ntohs等)主要用於從一臺機器移動數據到另一個。如果您只是在一臺機器上操作數據,那麼在沒有任何進一步的儀式的情況下進行位移是完全正確的 - 移位(至少在C和C++中)的定義是乘以/除以2的冪,所以無論機器是大端還是小端,它的工作原理都是一樣的。

如果需要(至少可能)將數據從一臺機器移動到另一臺機器,在發送數據前使用htonl,當您收到數據時使用ntohl通常是合理的。這可能完全是nops(在BE到BE的情況下),兩個相同的轉換可以相互抵消(LE到LE),或者實際上導致交換字節(LE到BE,反之亦然)。

+0

謝謝你的改寫澄清! +1 – Alexander 2011-04-13 00:26:54

3

雖然它會影響我的操作完全在於我將錯誤地移動(?)

號的結果將是相同的,無論端序架構。位移和旋轉就像普通的算術運算一樣。在小端和大端架構上,2 + 2是一樣的嗎?當然。 2 << 2也是一樣的。

當你直接處理內存時,會出現小的和大的endian問題。你會遇到的問題,當您執行以下操作:

char bytes[] = {1, 0, 0, 0}; 
int n = *(int*)bytes; 

在小端機,正將等於00000001。在大端機器上,n將等於0x01000000。這是你必須交換字節的時候。

+0

是的,這是有道理的,我一直認爲向左移動會移動內存中的整數(可視化它爲其他人填充後留下額外的零),而不僅僅是乘以2的冪,並將其他數字加入到特定點。 – Alexander 2011-04-13 02:44:23

1

FWIW,我想很多這裏所說的是正確的。但是,如果程序員在編碼時考慮了字節順序,比如說使用掩碼進行按位檢查和操作,那麼跨平臺結果可能會出乎意料。

您可以在運行時確定 '字節序' 如下:

#define LITTLE_ENDIAN 0 
#define BIG_ENDIAN 1 

int endian() { 
    int i = 1; 
    char *p = (char *)&i; 

    if (p[0] == 1) 
     return LITTLE_ENDIAN; 
    else 
     return BIG_ENDIAN; 
} 

...並進行相應處理。

我借用了這裏的代碼片段:http://www.ibm.com/developerworks/aix/library/au-endianc/index.html?ca=drs-,這裏也有對這些問題的精彩討論。

心連心 -

佩裏