Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/63.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/tensorflow/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C在减法过程中检查溢出_C_Bitwise Operators_Integer Overflow - Fatal编程技术网

C在减法过程中检查溢出

C在减法过程中检查溢出,c,bitwise-operators,integer-overflow,C,Bitwise Operators,Integer Overflow,我一直在尝试确定在减去两个32位数字时是否存在溢出。我得到的规则是: Can only use: ! ~ & ^ | + << >> * Max uses: 20 Example: subCheck(0x80000000,0x80000000) = 1, * subCheck(0x80000000,0x70000000) = 0 No conditionals, loops, additional functions, or casting

我一直在尝试确定在减去两个32位数字时是否存在溢出。我得到的规则是:

Can only use: ! ~ & ^ | + << >>
 *   Max uses: 20
Example: subCheck(0x80000000,0x80000000) = 1,
 *       subCheck(0x80000000,0x70000000) = 0
No conditionals, loops, additional functions, or casting

我现在意识到我不能在实际函数(-)中使用减法,所以我的整个函数无论如何都是无用的。如何使用与减法不同的方法,并仅使用位运算来确定是否存在溢出?

为了避免未定义的行为,我将假设整数以二的补码表示,从您对
sX
sY
sDif
的计算中推断出来。我还将假定
sizeof(int)
为4。如果只处理32位整数,则最好使用
int32\u t
,因为
int
的大小可能因平台而异

因为你可以使用加法,你可以把减法看作是一个数的负数的加法。存储在二的补码中的数字可以通过翻转所有位并加一来求反。这将给出以下修改后的代码:

int ny = 1 + ~y; // -y
int dif = x + ny; // dif is x - y
int sX = x >> 31; // get the sign of x
int sNY = ny >> 31; // get the sign of -y
int sDif = dif >> 31; // get the sign of the difference
return ((sX ^ sNY) | (~sDif ^ sX)); // if the sign of x and the sign of y 
                                    // are the same, no overflow. If the
                                    // sign of dif is the same as the signs
                                    // of x and -y, no overflow.

谢谢大家的帮助!以下是我解决问题的方法:

int ny = 1 + ~y; // -y
int dif = x + ny; // dif is x - y
int sX = x >> 31; // get the sign of x
int sY = y >> 31; // get the sign of -y
int sDif = dif >> 31; // get the sign of the difference
return (!(sX ^ sY) | !(sDif ^ sX));

我试过的每一个案例都有效。我改变了@HackerBoss的建议,将符号改为y而不是ny,然后在return语句中反转两个检查。这样,如果符号相同,或者如果结果的符号和x的符号相同,则返回true。

我想知道是什么学校给出了这些完全没有大脑的作业。至少它介绍了按位运算和两个负值的互补存储。
a-b
溢出发生时。OP尝试只使用位运算符和
进行求解依赖于UB或实现定义的行为。我认为如果不依赖于未定义的行为,这是不可能的。基本上,您的目标是按照chux编写的方式表示检查,但只使用登记的运算符。我不知道如何实现
返回值
1
是否意味着有溢出或没有溢出?P=正N=负。P-P不能溢出。N-N不能溢出。如果减法结果为负,则P-N溢出。如果减法的结果为正,则N-P溢出。您的代码实际上执行溢出的操作,并随后进行检查。这是行不通的:有符号整数溢出在C中有未定义的行为。它当然适用。二的补码是一个正交关系。我的意思是C实现可以使用二的补码、一的补码或符号/大小。无论是哪种类型,有符号整数溢出都有未定义的行为。不同意。C不要求使用2的补码的平台在溢出时定义良好,正如这个答案所希望的那样。看见
int ny = 1 + ~y; // -y
int dif = x + ny; // dif is x - y
int sX = x >> 31; // get the sign of x
int sY = y >> 31; // get the sign of -y
int sDif = dif >> 31; // get the sign of the difference
return (!(sX ^ sY) | !(sDif ^ sX));