2014-09-22 113 views
1

作爲一個謎題的一部分,我被要求實現一個函數來檢查兩個int是否可以一起添加而不會溢出。法律運作:! 〜&^| + < < >>。&C的奇怪行爲在C中爲&

例如對於x = 0x80000000的且y = 0x80000000的函數應該返回0,因爲它是溢出,但對於x = 0x80000000的且y = 0x70000000的結果將是1。

我的解決方案到目前爲止是:

int addOK(int x, int y) { 
    int mask = ~(1 << 31);  // 0x7fffffff 
    int newX = (mask & (x >> 1)); // Shift 1 to the right to make space for overflow bit 
    int newY = (mask & (y >> 1)); 
    int add = newX + newY;  // Add shifted x and y - overflow bit will be the MSB 
    int res = (add & ~mask);  // Set all bits to 0 except MSB - MSB 1 iff overflow 0 otherwise 
    int endRes = !res;   // 0x80000000 -> 0x00000000, 0x00000000 -> 0x00000001 
    printf("mask %x newX %x newY %x add %x ~mask %x res %x endRes %x\n",mask, newX, newY, add, ~mask, res, endRes); 
    return endRes; 
} 

功能打印以下爲X = 0x80000000的和y = 0x80000000的:

mask 7fffffff newX 40000000 newY 40000000 add 80000000 ~mask 80000000 res 0 endRes 1 

現在我的問題是,爲什麼是res 0?它應該是0x80000000,因爲add~mask都是0x80000000。任何人都可以向我解釋這種行爲嗎?

+5

不能重現:http://ideone.com/an8ocK – clcto 2014-09-22 20:04:08

+3

你知道轉移到符號位[是壞](http://stackoverflow.com/questions/4009885/arithmetic-bit-shift-on-a -signed-integer),對嗎?你不只是使用'INT_MAX'而不是試圖自己去設計它的任何特殊原因? – WhozCraig 2014-09-22 20:05:01

+0

好的,謝謝;這很奇怪。我不應該爲這個任務使用大於一個字節的任何常量。 – user3273046 2014-09-22 20:19:29

回答

0

我在Linux 32位上試過我的代碼,並且沒有發生上面提到的特定問題。

我得出結論,問題是由於操作系統和/或我使用的編譯器。由於我自己並沒有編寫測試或makefile文件,而且迄今爲止對C還不夠熟悉,所以我仍然不完全明白出了什麼問題。

但正如帕特指出(謝謝)

你拍攝的符號或無符號溢出?你所有的值都是有符號的,但你顯然只是在尋找第31位的結果,這不是一個有符號的溢出。 -pat

我寫的算法首先被打破。我腦海中有一個錯誤的想法。我必須檢查是否有兩個負號被添加並溢出到正的一個或兩個正數到負數時發生的有符號溢出。 (根據二進制補碼算法)。

如果有人有興趣,這裏是我工作的代碼:

int addOK(int x, int y) { 
    int mask = 1 << 31; // 0x80000000 
    int msbX = mask & x; // Set all bit to 0 except sign bit 
    int msbY = mask & y; 
    int msbSum = mask & (x + y); 
    int prob1 = !(msbX^msbY); // == 1 iff x and y have the same sign - thats when an overflow may occur 
    int prob2 = !(msbX^msbSum); // == 0 iff x + y and x have a different sign - thats when an overfolow may occur 
    return (!prob1) | prob2;  // There is an overflow iff prob1 == 1 and prob2 == 0 
} 

在這段代碼中我問了一下上面甚至沒有出現問題,我可以直接在我的Mac再次運行。