2010-09-23 59 views
1
#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執行此操作。

回答

10

的隱藏式轉換爲:

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可以進行簽名或未簽名;所有其他類型總是默認簽名。

+2

值得注意的是,在一般情況下,有符號無符號*轉換*不是基於重新解釋。事實上,轉換和重新解釋是非常非常不同的東西,而我們在這種情況下的確是一種*轉換*,而不是重新解釋。 – AnT 2010-09-23 16:21:29

+0

++,很好的答案 – 2010-09-23 17:19:57

4

簡答:該部門首先將x提升爲unsigned。只有這樣,結果纔會回到signed short

龍答:讀this SO thread.

3

的問題來自於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; 
} 
1

每次在加法和乘法算術運算中混合使用「大」有符號和無符號值時,無符號類型爲「勝」,評估在無符號類型的域中執行(「大」意味着int和更大)。如果您的原始簽名值爲負數,則首先會根據簽名到未簽名轉換的規則將其轉換爲正值無符號值。在你的情況下,-13701將變成UINT_MAX + 1 - 13701,結果將被用作股息。

請注意,在典型的32位int平臺上進行有符號無符號轉換的結果將導致無符號值4294953595。除以3後,您將獲得1431651198。此值太大,無法在具有16位short類型的平臺上強制爲short對象。試圖這樣做會導致實現定義的行爲。所以,如果您的平臺的屬性與我的假設相同,那麼您的代碼會生成實現定義的行爲。從形式上講,你所獲得的「毫無意義的」價值無非就是該實現定義的行爲的具體表現形式。有可能的是,如果您編譯的代碼啓用了溢出檢查(如果您的編譯器支持它們),它會陷入分配。

+0

實際上,它不是未定義的行爲:標準說結果是實現定義的或者實現定義的信號被提出(轉換爲窄帶符號類型與計算過程中的溢出不同)。 – caf 2010-09-24 00:10:39

+0

@caf:你說得很對。感謝您的更正。嗯......我記得自己多次提出這個更正的評論,但在這種情況下,我忘記了所有關於它的:) – AnT 2010-09-24 00:59:40