让我们拥有
int a, b, c; // may be char or float, anything actually
c = a + b;
让int类型由4个字节表示。假设a + b需要1位多于4个字节(即,假设结果是1 00 .... 0(32个零,二进制))。这将导致C = 0,我确信计算机的微处理器会设置某种溢出标志。是否有内置的方法在C中检查这个?
我实际上正在构建一个1024位长的数字类型(例如,int是一个32位长的内置数字类型)。我尝试使用带有128个元素的unsigned char类型数组。我还需要对这些数字定义加法和减法运算。我已经编写了添加代码,但我在减法方面遇到了问题。我不需要担心得到负面结果,因为我称之为减法函数的方式总是确保减法的结果总是正的,但是为了实现减法函数我需要以某种方式得到减数的2的补码,它是我自定义的1024位数。
如果难以理解我的描述,我很抱歉。如果需要,我会详细说明。我包含了我的代码,用于添加函数和不完整的减法函数。 NUM_OF_WORDS
是一个声明为
#define NUM_OF_WORDS 128
如果您不理解我的问题或我的代码的任何部分,请告诉我。
PS:我没有看到如何在此论坛上传附件,因此我将您引导至其他网站。我的代码可以在那里找到
click on download in this page
顺便说一句,我发现this
我打算替换INT_MAX by UCHAR_MAX
因为我的1024位数字由char类型数组(8位变量)组成
这种检查是否适用于所有情况?
是的我正在研究密码学
我需要为1024位大小的整数实现蒙哥马利乘法例程
我也考虑过使用GMP库,但却找不到如何使用它
我查了一个教程,经过一些小修改后,我能够在VC ++ 6中构建GMP项目文件,这导致了很多.obj文件,但现在我不知道如何处理它们。
如果我能编写自己的数据类型仍然会很好,因为它可以让我完全控制我的自定义数据类型的算术运算如何工作,而且我还需要能够将它从1024位扩展到更大的数字。未来。
答案 0 :(得分:4)
如果您要添加无符号数字,则可以执行此操作
c = a+b;
if (c<a) {
// you'll get here if and only if overflow has occurred
}
你甚至可能会发现你的编译器足够聪明,可以通过检查overflow或carry标志来实现它,而不是进行额外的比较。例如,我刚把它喂给gcc -O3 -S
:
unsigned int foo() {
unsigned int x=g(), y=h();
unsigned int z = x+y;
return z<0 ? 0 : z;
}
并得到了代码的关键位:
movl $0, %edx
addl %ebx, %eax
cmovb %edx, %eax
你会注意到没有额外的比较指示。
答案 1 :(得分:3)
与普遍看法相反,int
溢出导致未定义的行为。这意味着一旦a + b
溢出,使用此值(或做任何其他事情)就没有意义了。环绕是大多数机器在发生溢出时碰巧做的事情,但它们也可能爆炸。
要检查在添加两个非负整数int
和a
时是否会发生b
溢出,您可以执行以下操作:
if (INT_MAX - b < a) {
/* int overflow when evaluating a+b */
}
这是因为如果a + b > INT_MAX
,则INT_MAX - b < a
,但INT_MAX - b
不会溢出。
您必须特别注意b
为否定的情况,这是读者留下的练习;)
关于您的实际目标:1024位数字与32位数字完全相同。选择完全不同的方法可能更有希望,例如,使用非常大的基数B表示数字,例如,链接的数字列表。通常,选择B使得B = sqrt(INT_MAX)
,因此数字的乘法不会溢出机器的int
类型。
这样,您可以表示任意大数,其中“任意”表示“仅受可用主内存量的限制”。
答案 2 :(得分:1)
如果您使用的是未签名的号码,那么a <= UINT_MAX
,b <= UINT_MAX
和a + b >= UINT_MAX
,则c = (a + b) % UINT_MAX
将始终小于a
和{ {1}}。这是唯一可能发生这种情况的情况。
所以你可以用这种方式检测溢出。
b
答案 3 :(得分:1)
可能对此主题有用的信息:
答案 4 :(得分:0)
您可以基于C语言的特定功能构建解决方案。根据规范,当你添加两个无符号整数时,“结果值与真实结果的模2 ^ n一致”(Harbison和Steele的“C - 参考手册”)。这意味着您可以使用一些简单的算术检查来检测溢出:
#include <stdio.h>
int main() {
unsigned int a, b, c;
char *overflow;
a = (unsigned int)-1;
for (b = 0; b < 3; b++) {
c = a + b;
overflow = (a < b) ? "yes" : "no";
printf("%u + %u = %u, %s overflow\n", a, b, c, overflow);
}
return 0;
}
答案 5 :(得分:0)
两个操作数和结果的x或MSB。此操作的结果是溢出标志。
但是,如果结果是否正确,那将无法显示。 (它可能是正确的结果,即使是溢出)例如3 +( - 1)是2个溢出。
为了确定使用带符号的算术,你需要检查两个operdas是否都是相同的符号(MSB的xor)。
答案 6 :(得分:-1)
一旦你向INT_MAX加1,你最终得到INT_MIN(即溢出) 在C中,没有可靠的方法来测试溢出,因为所有32个字节都用于表示整数(而不是状态标志)。您只能测试以查看您获得的号码是否在有效范围内,如您的链接。
你会得到答案,建议你可以测试if (c < a)
,但请注意你可以将a和/或b的值溢出到它们的加法形成一个大于a的数字的点(但仍然溢出)