#include "stdio.h"
int main()
{
int x = -13701;
unsigned int y = 3;
signed short z = x/y;
printf("z = %d\n", z);
return 0;
}
我希望答案是-4567。我得到「z = 17278」。 爲什麼這些數字的提升會導致17278?發生了哪些類型轉換?
我在Code Pad執行此操作。
#include "stdio.h"
int main()
{
int x = -13701;
unsigned int y = 3;
signed short z = x/y;
printf("z = %d\n", z);
return 0;
}
我希望答案是-4567。我得到「z = 17278」。 爲什麼這些數字的提升會導致17278?發生了哪些類型轉換?
我在Code Pad執行此操作。
的隱藏式轉換爲:
signed short z = (signed short) (((unsigned int) x)/y);
當您混合符號和無符號類型的無符號也會取勝。將x
轉換爲unsigned int
,除以3,然後將該結果下轉換爲(有符號)short
。具有32位整數:
(unsigned) -13701 == (unsigned) 0xFFFFCA7B // Bit pattern
(unsigned) 0xFFFFCA7B == (unsigned) 4294953595 // Re-interpret as unsigned
(unsigned) 4294953595/3 == (unsigned) 1431651198 // Divide by 3
(unsigned) 1431651198 == (unsigned) 0x5555437E // Bit pattern of that result
(short) 0x5555437E == (short) 0x437E // Strip high 16 bits
(short) 0x437E == (short) 17278 // Re-interpret as short
順便說,該signed
關鍵字是不必要的。 signed short
是說short
更長的一種方式。唯一需要明確signed
的類型是char
。根據平臺,char
可以進行簽名或未簽名;所有其他類型總是默認簽名。
簡答:該部門首先將x
提升爲unsigned
。只有這樣,結果纔會回到signed short
。
龍答:讀this SO thread.
的問題來自於unsigned int y
。的確,x/y
變爲無符號。它適用於:
#include "stdio.h"
int main()
{
int x = -13701;
signed int y = 3;
signed short z = x/y;
printf("z = %d\n", z);
return 0;
}
每次在加法和乘法算術運算中混合使用「大」有符號和無符號值時,無符號類型爲「勝」,評估在無符號類型的域中執行(「大」意味着int
和更大)。如果您的原始簽名值爲負數,則首先會根據簽名到未簽名轉換的規則將其轉換爲正值無符號值。在你的情況下,-13701
將變成UINT_MAX + 1 - 13701
,結果將被用作股息。
請注意,在典型的32位int
平臺上進行有符號無符號轉換的結果將導致無符號值4294953595
。除以3
後,您將獲得1431651198
。此值太大,無法在具有16位short
類型的平臺上強制爲short
對象。試圖這樣做會導致實現定義的行爲。所以,如果您的平臺的屬性與我的假設相同,那麼您的代碼會生成實現定義的行爲。從形式上講,你所獲得的「毫無意義的」價值無非就是該實現定義的行爲的具體表現形式。有可能的是,如果您編譯的代碼啓用了溢出檢查(如果您的編譯器支持它們),它會陷入分配。
值得注意的是,在一般情況下,有符號無符號*轉換*不是基於重新解釋。事實上,轉換和重新解釋是非常非常不同的東西,而我們在這種情況下的確是一種*轉換*,而不是重新解釋。 – AnT 2010-09-23 16:21:29
++,很好的答案 – 2010-09-23 17:19:57