Questions tagged «integer-overflow»

当运算结果大于基础整数类型可以表示的最大值时,就会发生整数溢出。

30
如何检测无符号整数乘法溢出?
Наэтотвопросестьответына 堆栈溢出нарусском:МожнолинаязыкахC / C ++определитьцелочисленноепереполнение? 我在C ++编写一个程序来找到所有的解决方案一b = c ^,其中一个,b和c ^一起使用所有的数字0-9只出现一次。该程序循环了a和b的值,并且每次在a,b和a b上运行一个数字计数例程,以检查是否满足数字条件。 然而,当可以产生伪解一个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溢出是未定义的行为,因此您必须在没有实际引起它的情况下对其进行检测。有关添加之前的有符号的int溢出,请参阅在C / C ++中检测有符号的溢出。
618 c++  c  integer-overflow 

4
(-2147483648> 0)在C ++中返回true吗?
-2147483648是32位整数类型的最小整数,但似乎会在if(...)句子中溢出: if (-2147483648 > 0) std::cout << "true"; else std::cout << "false"; 这将true在我的测试中打印。但是,如果将-2147483648强制转换为整数,结果将有所不同: if (int(-2147483648) > 0) std::cout << "true"; else std::cout << "false"; 这将打印false。 我很困惑。谁能解释一下? 更新02-05-2012: 感谢您的评论,在我的编译器中,int的大小为4个字节。我正在使用VC进行一些简单的测试。我已经更改了问题的描述。 这在这篇文章中得到了很多很好的答复,AndreyT给出了关于编译器将如何对此类输入进行操作以及如何实现此最小整数的非常详细的解释。另一方面,qPCR4vir提供了一些相关的“好奇心”以及如何表示整数。好厉害!


5
为什么未定义整数溢出定义行为,但没有定义整数溢出?
C和C ++标准都很好地定义了无符号整数溢出。例如,C99标准(§6.2.5/9)指出 涉及无符号操作数的计算永远不会溢出,因为无法用所得的无符号整数类型表示的结果的模数要比该所得类型可以表示的最大值大一模。 但是,两个标准都指出有符号整数溢出是未定义的行为。同样,根据C99标准(§3.4.3/1) 未定义行为的一个示例是整数溢出时的行为 是否存在这种差异的历史原因(甚至更好!)是技术原因?


15
如何避免expr中的溢出。A B C D
我需要计算一个看起来像:的表达式 A*B - C*D,其类型为:signed long long int A, B, C, D; 每个数字都可以很大(不会溢出其类型)。虽然A*B可能导致溢出,但表达式A*B - C*D的确很小。如何正确计算? 例如:MAX * MAX - (MAX - 1) * (MAX + 1) == 1,其中MAX = LLONG_MAX - n和n-一些自然数。
161 c++  c  integer-overflow 


6
(A + B + C)≠(A + C + B)和编译器重新排序
将两个32位整数相加会导致整数溢出: uint64_t u64_z = u32_x + u32_y; 如果首先将32位整数之一转换为64位整数或将其添加到64位整数,则可以避免这种溢出。 uint64_t u64_z = u32_x + u64_a + u32_y; 但是,如果编译器决定重新排序添加项: uint64_t u64_z = u32_x + u32_y + u64_a; 整数溢出仍可能发生。 是否允许编译器进行这种重新排序,还是我们可以信任它们以注意到结果不一致并按原样保留表达式顺序?

14
如何检查Java中的两个数字是否会导致溢出?
我想处理将两个数字相乘会导致溢出的特殊情况。代码看起来像这样: int a = 20; long b = 30; // if a or b are big enough, this result will silently overflow long c = a * b; 那是一个简化的版本。在实际程序中,a并且b在运行时从其他地方获取。我想要实现的是这样的: long c; if (a * b will overflow) { c = Long.MAX_VALUE; } else { c = a * b; } …

8
高效的无符号到无符号转换避免实现定义的行为
我想定义一个函数,该函数接受unsigned intas作为参数,int并向该参数返回全模UINT_MAX + 1。 第一次尝试可能看起来像这样: int unsigned_to_signed(unsigned n) { return static_cast<int>(n); } 但是,正如任何语言律师所知,对于大于INT_MAX的值,从无符号转换为有符号是由实现定义的。 我要实现这一点,以便(a)仅依赖规范要求的行为;(b)它可以在任何现代机器和优化的编译器上编译为no-op。 至于奇异的机器...如果没有符号的int与未签名的int模UINT_MAX + 1一致,那么我想抛出一个异常。如果不止一个(我不确定这是可能的),那么我要最大的一个。 好,第二次尝试: int unsigned_to_signed(unsigned n) { int int_n = static_cast<int>(n); if (n == static_cast<unsigned>(int_n)) return int_n; // else do something long and complicated } 当我不使用典型的二进制补码系统时,我不太关心效率,因为我的拙见认为这不太可能。而且,如果我的代码成为2050年无处不在的符号幅度系统的瓶颈,那么我敢打赌,有人可以弄清楚这一点,然后对其进行优化。 现在,第二次尝试非常接近我想要的。尽管强制转换int为某些输入的实现定义,但是unsigned标准保证了强制转换为保留对UINT_MAX + 1取模的值。因此,条件条件确实会检查我想要的内容,并且在任何可能遇到的系统上,它都不会编译成任何东西。 但是...我仍然在int不首先检查它是否将调用实现定义的行为的情况下进行投射。在2050年的某个假设系统上,它可以做谁知道什么。所以说我要避免这种情况。 问题:我的“第三次尝试”应该是什么样的? 回顾一下,我想: 从unsigned int转换为signed int …

12
在循环中的什么时候整数溢出会变成未定义的行为?
这是一个示例来说明我的问题,其中涉及一些我无法在此处发布的更复杂的代码。 #include <stdio.h> int main() { int a = 0; for (int i = 0; i < 3; i++) { printf("Hello\n"); a = a + 1000000000; } } 该程序在我的平台上包含未定义的行为,因为a它将在第3个循环中溢出。 这是否会使整个程序具有未定义的行为,还是仅在实际发生溢出之后?编译器是否可以解决a 将导致溢出的问题,以便它可以声明整个循环未定义,并且即使它们都在溢出之前发生,也不必费心运行printfs? (尽管标记为C和C ++有所不同,但如果它们不相同,我会对两种语言的答案都感兴趣。)

3
在C ++中,有符号整数溢出仍然是未定义的行为吗?
众所周知,有符号整数溢出是未定义的行为。但是C ++ 11cstdint文档中有一些有趣的东西: 有符号整数类型,其宽度分别精确地为8、16、32和64位,没有填充位,并且对负值使用2的补码(仅在实现直接支持该类型时提供) 见链接 这里是我的问题:由于标准明确地说,对int8_t,int16_t,int32_t和int64_t负数是2的补,还是溢出这些类型的未定义的行为吗? 编辑我检查了C ++ 11和C11标准,这是我发现的内容: C ++ 11,第18.4.1节: 标头定义了与C标准中的7.20相同的所有函数,类型和宏。 C11,第7.20.1.1节: typedef名称intN_t指定宽度为N,无填充位和二进制补码表示形式的带符号整数类型。因此,int8_t表示具有正好8位宽度的这种有符号整数类型。

4
程序在在线IDE上表现异常
我遇到了以下C ++程序(源代码): #include <iostream> int main() { for (int i = 0; i < 300; i++) std::cout << i << " " << i * 12345678 << std::endl; } 它看起来像一个简单的程序,并在我的本地计算机上提供正确的输出,例如: 0 0 1 12345678 2 24691356 ... 297 -628300930 298 -615955252 299 -603609574 但是,在诸如codechef之类的在线IDE上,它提供以下输出: 0 0 1 12345678 2 24691356 …

12
在C / C ++中检测签名溢出
乍一看,这个问题似乎与“如何检测整数溢出”重复出现。,但实际上有很大的不同。 我发现,虽然检测无符号整数溢出非常简单,但是在C / C ++中检测带符号溢出实际上比大多数人想象的要困难。 最明显但最幼稚的方式是: int add(int lhs, int rhs) { int sum = lhs + rhs; if ((lhs >= 0 && sum < rhs) || (lhs < 0 && sum > rhs)) { /* an overflow has occurred */ abort(); } return sum; } 这样做的问题是根据C标准,有符号整数溢出是未定义的行为。 换句话说,根据标准,甚至在导致签名溢出时,程序就如同取消引用空指针一样无效。因此,您不能导致未定义的行为,然后尝试在事后检测溢出,如上述后置条件检查示例中所示。 即使上面的检查可能在许多编译器上都有效,但您不能指望它。实际上,由于C标准说未定义有符号整数溢出,因此某些编译器(如GCC)会在设置优化标志时优化上述检查,因为编译器认为有符号溢出是不可能的。这完全中断了检查溢出的尝试。 因此,另一种检查溢出的可能方法是: …


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.