2013-10-21 24 views
21

我想通過一個套接字傳遞一個32位有符號整數x。爲了讓接收器知道哪個字節順序,我在發送之前調用htonl(x)htonl預計會有uint32_t,但我想確定在將我的int32_t投射到uint32_t時會發生什麼情況。在signed和unsigned int之間是否保持精確的位模式?

int32_t x = something; 
uint32_t u = (uint32_t) x; 

是否總是在xu每個字節會完全一樣的情況下?怎麼樣鑄造回:

uint32_t u = something; 
int32_t x = (int32_t) u; 

我認識到,投大無符號值的負值,但這並不重要,因爲我只是鑄造回到另一端。但是如果使用實際字節進行強制轉換,那麼我無法確定強制轉換會返回相同的值。

回答

19

一般來說,C中的投射是根據值來指定的,而不是位模式 - 前者將被保留(如果可能的話),但後者不一定如此。如果兩個補碼錶示沒有填充 - 這對於固定整數類型是強制性的 - 這個區別並不重要,並且演員確實是一個noop。

但即使從signed到unsigned的轉換會改變位模式,將其再次轉換回原來的值也會恢復原始值 - 超出範圍無符號簽名轉換的警告是實現定義的,可能會在溢出時發出一個信號。

對於完全的可移植性(這可能會矯枉過正),您需要使用類型雙擊而不是轉換。這可以通過以下兩種方式之一進行:

通過指針蒙上,即

uint32_t u = *(uint32_t*)&x; 

,你應該小心,因爲它可能違反了有效的打字規則(但罰款整數符號/無符號變種類型)或通過工會,也就是說,如果你想避免不確定的行爲

uint32_t u = ((union { int32_t i; uint32_t u; }){ .i = x }).u; 

也可用於例如將從doubleuint64_t,你可能不會做指針強制轉換。

+2

不錯,+1與工會的解決方案。 –

+0

太棒了,這是我想知道的。因此,它將始終工作提供簽名ints使用二進制補碼來表示,這幾乎總是如此。那是對的嗎? – Flash

+1

@Andrew:正確 - 甚至在非二進制補碼硬件上,編譯器將不得不僞裝成固定寬度的整數類型,或者根本不提供它們;在溢出時產生一個信號在實踐中也不會成爲問題 – Christoph

6

在C語言中使用Casts來表示「類型轉換」和「類型消歧」。如果你有類似的東西

(float) 3 

然後它是一個類型轉換,實際位改變。如果你說

(float) 3.0 

這是一種消除歧義的類型。

假設2的補碼錶示(見下文評論),當你施放一個intunsigned int,位模式沒有改變,只是它的語義含義;如果你把它放回去,結果總是正確的。它屬於類型消歧的情況,因爲沒有位被改變,只是計算機解釋它們的方式。

請注意,理論上,可能不會使用2的補碼,並且unsignedsigned可能具有非常不同的表示,實際的位模式可能會在此情況下發生變化。

然而,從C11(當前的C標)時,實際上被保證sizeof(int) == sizeof(unsigned int)

(§6.2.5/ 6)對於每個符號整數類型,有相對應的 (但是,它使用存儲相同量的(包括 符號信息)並具有相同的對準要求不同)的無符號整數型(帶 關鍵字無符號指定)[...]

我要說的是在實踐中,你可以假設它是安全的。

+1

這是不正確的 - 簽名到無符號轉換可能會改變位模式 - 它恰好如此,它不會發生在具有相同填充的二進制補碼錶示 – Christoph

+0

@Christoph好點。我更新了我的答案。 –

+1

現在看起來不錯:+1 – Christoph

2

這應該永遠是安全的,因爲intXX_t類型保證在補如果它們存在:

7.20.1.1精確寬度的整數類型typedef名intN_t指定一個符號整型寬度爲N,沒有填充位,以及兩個補碼錶示。因此,int8_t表示寬度恰好爲8位的有符號整數 。

理論上,該反向轉換從uint32_tint32_t被實現定義的,作爲所有unsignedsigned轉換。但我無法想象一個平臺的表現會與你期望的不同。

如果你想真正確定這一點,你仍然可以手動進行轉換。你只需要測試> INT32_MAX的值,然後做一些數學運算。即使你有系統地做,一個體面的編譯器應該能夠檢測並優化它。

+0

,我可以設想一個陷阱整數溢出的平臺在類型轉換時可能會這樣做(例如,編譯器可能會生成一個無用的「add 0」指令觸發它);如果有一個編譯器在默認情況下(或者根本就是這樣)編譯,我會感到非常驚訝;另外,我寧願選擇類型雙向比檢查「INT32_MAX」 - 固定整數不帶有陷阱表示,因此就C標準而言,它和安全性一樣,並且實際上捕獲了前進中的意圖 – Christoph

相關問題