&的奇怪行为C中的操作员

时间:2014-09-22 19:58:59

标签: c bitwise-operators bitwise-and

作为拼图的一部分,我被要求实现一个函数,该函数检查两个整数是否可以一起添加而不会溢出。法律操作:! 〜& ^ | +<< >>

例如,对于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。任何人都可以向我解释这种行为吗?

1 个答案:

答案 0 :(得分:0)

我在Linux 32位上尝试了我的代码,并且没有出现上述特定问题。

我的结论是问题是由于我使用的OS和/或编译器。由于我自己没有编写测试或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上运行它。