当前位置: 首页 > 面试题库 >

如何检测无符号整数乘法溢出?

潘秦斩
2023-03-14
问题内容

我在C ++编写一个程序来找到所有的解决方案一b = c ^,其中一个,b和c ^一起使用所有的数字0-9只出现一次。该程序循环了a和b的值,并且每次在a,b和a b上运行一个数字计数例程,以检查是否满足数字条件。

但是,当a b超出整数限制时,可能会生成伪解。我最终使用如下代码检查了这一点:

unsigned long b, c, c_test;
...
c_test=c*b;         // Possible overflow
if (c_test/b != c) {/* There has been an overflow*/}
else c=c_test;      // No overflow

有没有更好的测试溢出方式?我知道有些芯片具有发生溢出时设置的内部标志,但我从未见过通过C或C ++访问它。

请注意,在C和C ++中,签名 int溢出是未定义的行为,因此您必须在没有实际引起它的情况下对其进行检测。


问题答案:

Clang 3.4+和GCC 5+提供了经过检查的算术内置函数。它们提供了一个非常快速的解决方案,特别是与位测试安全检查相比。

对于OP问题中的示例,它将像这样工作:

unsigned long b, c, c_test;
if (__builtin_umull_overflow(b, c, &c_test))
{
    // Returned non-zero: there has been an overflow
}
else
{
    // Return zero: there hasn't been an overflow
}

Clang文档没有指定c_test如果发生溢出是否包含溢出结果,但是GCC文档说确实包含。鉴于这两个都喜欢__builtin兼容,因此可以安全地假设这也是Clang的工作方式。

有一个__builtin对每个运算,可以溢出(加法,减法,乘法),用符号和无符号的变体,对于int尺寸,长尺寸,以及长长的大小。名称的语法为__builtin_[us](operation)(l?l?)_overflow

  • u对于未签名或s对签名的 ;
  • 操作中的一个add,sub或mul;
  • 没有l后缀表示操作数是ints;一种l手段long; 2 l的平均值long long。

因此,对于一个选中的带符号长整数加法运算,它将为__builtin_saddl_overflow。完整列表可在Clang文档页面上找到。

GCC 5+和锵3.8+还提供通用内建的工作,而无需指定值的类型:__builtin_add_overflow,__builtin_sub_overflow__builtin_mul_overflow。这些也适用于小于的类型int。

内建工具降低到最适合该平台的水平。在x86上,它们检查进位,溢出和符号标志。

Visual Studiocl.exe没有直接等效项。对于无符号的加法和减法,包括 将允许您使用 `addcarry_uNNsubborrow_uNN(其中NN是位数,例如 addcarry_u8或`subborrow_u64)。他们的签名有点晦涩:

unsigned char _addcarry_u32(unsigned char c_in, unsigned int src1, unsigned int src2, unsigned int *sum);
unsigned char _subborrow_u32(unsigned char b_in, unsigned int src1, unsigned int src2, unsigned int *diff);

c_in/b_in是输入上的进位/借位标志,返回值是输出上的进位/借位。它似乎没有等效的有符号运算或乘法。

否则,适用于Windows的Clang现在可以投入生产了(对于Chrome来说已经足够了),因此也可以选择。



 类似资料:
  • 我正在读一篇关于整数安全性的文章。以下是链接:http://ptgmedia.pearsoncmg.com/images/0321335724/samplechapter/seacord_ch05.pdf 在第166页,有这样一句话: 涉及无符号操作数的计算永远不会过流,因为不能由结果无符号整数类型表示的结果将被模化为比结果类型可以表示的最大值大一的数字。 这是什么意思?感谢您的回复。

  • 我正在简单的C程序中试验无符号int数据类型和主方法参数。作为一个实验,我写了一个程序,从命令行获取一个int数作为main方法的参数,并对该数和0之间的每个整数求和。 例如,程序计算 f(n) = (1 2 3... n) 当 n 时有效 我开始注意到的第一件事是当f(n) 我手动发现数学上的最大值,我的程序生成的结果将是有效的(例如,在整数溢出之前),对于有符号整数为65535,对于无符号in

  • 问题内容: 我知道有人多次问过这个话题,但是 我的问题是关于完整32位int的溢出 。例如: 我发现话题与这个类似的问题,但该算法是不完美的。 有没有简单,快速,安全的方法来检查此内容? 问题答案: 从Java 8开始,该类中提供了一组方法: …以及很长的版本。 如果发生溢出,这些方法中的每一个都会引发。否则,如果它在该范围内,它们将返回正确的结果。 添加示例: 看到此代码在IdeOne.com上

  • 我正在练习Cay S.Horstmann的《Java SE 8 for the Really Impatient》一书中的练习。其中一个基于类中的改进的练习要求: 编写一个程序,使用< code>int值和无符号运算,对0和232 - 1之间的数进行加、减、除和比较。说明为什么需要< code>divideUnsigned和< code>remainderUnsigned。 问题是,如果您添加2个

  • 未定义行为的一个例子是在flow上的整数行为 有没有一个历史的或者(甚至更好!)造成这种差异的技术原因是什么?

  • 问题内容: 如果我想将字符串转换为Java中的int,您知道我是否可以检测到溢出吗?我的意思是,字符串文字实际上表示的值大于MAX_INT? java doc没有提到它。.它只是说,如果不能将字符串解析为整数,它将通过FormatException没有提及有关溢出的问题。 问题答案: 如果我想在Java中将字符串转换为int,您是否知道我是否可以检测到溢出? 是。捕获解析异常将是正确的方法,但是这