2012-12-03 46 views
2

最近,我正在跟蹤網絡通信雙方具有不同字節順序時出現的錯誤。一方已經發出標記lastSegment的電報,而另一方仍在無休止地等待最後一段。Endianess in a byte

我讀到這段代碼:

#ifndef kBigEndian 
    struct tTelegram 
    { 
     u8 lastSegment : 1; 
     u8 reserved: 7; 
     u8 data[1]; 
    }; 
#else 
    struct tTelegram 
    { 
     u8 reserved: 7; 
     u8 lastSegment : 1; 
     u8 data[1]; 
    }; 
#endif 

我知道字節序而言多字節類型,例如,整型,長等,但爲什麼它在前面的代碼在乎呢? lastSegmentreserved位於單個字節內。

這是一個錯誤嗎?

+0

跨編譯器和體系結構的位打包佈局不可移植,並且是實現定義的。你不能認爲它會以同樣的方式完成。另請參閱:http://stackoverflow.com/questions/1490092/cc-force-bit-field-order-and-alignment – Joe

回答

1

說到位域,在運行在同一CPU上的不同編譯器之間,不保證訂購,甚至。理論上甚至可以通過使用相同編譯器更改標誌來更改順序(儘管公平地說,我必須補充說我從未見過這種情況發生)。

+0

因此,當通過網絡傳遞一個字節到另一端時,另一端不能保證獲得正確的值? –

+0

@EricZ:是的。或者更確切地說,真的*是*沒有人接受「正確的價值」。 –

+1

另一方會得到與發送的字節相同的字節......但接收該字節的程序可能編譯方式不同,因此它會將結構的成員變量與發送該字節的程序的不同位相關聯,這會導致混淆/不兼容,即使發件人和收件人使用相同的源代碼。如果避免使用C的位域功能,而是使用自己的位打包邏輯(使用位移位和位位移位和/或)來打包/解壓縮字節,則可以避免該特定陷阱。 –

2

你的結構中有16位。在32位或64位體系結構上,取決於字節位置,data可能在「之前」reservedlastSegment之後出現,或者在查看原始二進制文件時可能會出現「之後」。 IE如果我們考慮32位,你的結構可能會沿着32位邊界打包。這可能是這樣的:

padbyte1 padbyte2 data lastSegment+reserved 

,或者它可能看起來像這樣

lastSegment+reserved data padbyte1 padbyte2 

所以,當你把這些16位在電線然後重新詮釋他們的另一面,你知道,如果你」重新獲得datalastSegment

您的問題不在該字節內,其中datareservedlastSegment有關。

+0

因此,我應該改變endianness ifdef的位置,以便'lastSegment + reserved'出現在'data'前面在big endian中,並且在little endian的'data'之後。是對的嗎? –

+2

@EricZ:不,你應該完全避免使用位域,如果你關心的是一個定義良好的數據格式。 – jamesdlin