2011-07-07 92 views
8

對此有一個窺視。編譯器抱怨說我有一個整數溢出,但是當我查看C89標準的整數提升規則以及該表達式中的值時,似乎沒有溢出。C積分溢出?

[email protected]:~$ cat test.c 
#include <stdio.h> 
#include <inttypes.h> 

const uint32_t value = 
    (0x7F-0x00 + 1) * (256 + 256*256 + 256*256*256) + 
    (0xDF-0xC2 + 1) * (256 + 256*256 + 256*256*256); 

int 
main(void) 
{ 
    printf("value = %"PRIu32"\n", value); 
    return 0; 
} 
[email protected]:~$ gcc -std=c89 -pedantic -Wall -Wextra test.c 
test.c:5: warning: integer overflow in expression 
test.c:6: warning: integer overflow in expression 
test.c:6: warning: overflow in constant expression 
[email protected]:~$ ./a.out 
value = 2661195264 
[email protected]:~$ 

此外,谷歌確認2661195264的答案是該表達的正確值! (See this link

那麼,程序如何在有整數溢出時產生正確的值?更重要的是,該表達式中的整數溢出是如何開始的?

+0

也許它使用signed int而不是unsigned,那麼儘管計算了正確的無符號值,但在簽名操作中會發生溢出。 – Nobody

回答

14
(0x7F-0x00 + 1) * (256 + 256*256 + 256*256*256) 

具有值2155905024;最大可表示簽署 32位int2147483647,所以你確實產生了溢出。無論如何,它恰巧給了你預期的結果(你很幸運)。

請注意,您的整個初始化程序有簽名類型(特別是類型int),因爲沒有文字是後綴。該表達式被評估爲帶符號的整型,然後將結果值轉換爲無符號整數。

+2

...並注意'int'只需要16位,所以即使是'256 * 256'也可能是溢出。你可以通過爲每個常量使用'256UL'而不是'256'來解決這個問題。 – caf

2

雖然你的常量都是正數,但它們仍然是有符號整數。您溢出了有符號整數的範圍。將結果分配給變量時,結果將轉換爲無符號數據作爲最後一步。

加法,減法和乘法的位模式在有符號和無符號操作之間是相同的。雖然編譯器在這種情況下不需要提供正確的答案,但這只是最自然的結果。