我在C++编写一个程序来找到所有的解决方案一b = c ^,其中一个,b和c ^一起使用所有的数字0-9只出现一次.该方案在循环值一和b,并且在每次跑了数字计数程序一,b和一个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
Run Code Online (Sandbox Code Playgroud)
有没有更好的方法来测试溢出?我知道有些芯片有一个内部标志,当溢出发生时会设置,但我从未见过通过C或C++访问它.
请注意,在C和C++中,签名 int溢出是未定义的行为,因此您必须在不实际导致它的情况下检测它.有关添加前的signed int overflow,请参阅在C/C++中检测带符号的溢出
想象一下,我有两个无符号字节b和x.我需要计算bsubas b - x和baddas b + x.但是,我不希望在这些操作期间发生下溢/溢出.例如(伪代码):
b = 3; x = 5;
bsub = b - x; // bsub must be 0, not 254
Run Code Online (Sandbox Code Playgroud)
和
b = 250; x = 10;
badd = b + x; // badd must be 255, not 4
Run Code Online (Sandbox Code Playgroud)
显而易见的方法包括分支:
bsub = b - min(b, x);
badd = b + min(255 - b, x);
Run Code Online (Sandbox Code Playgroud)
我只是想知道是否有更好的方法来做到这一点,即通过一些hacky位操作?
我们知道CPython在数字变大时会无声地将整数提升为长整数(允许任意精度算术)。
我们如何检测的溢出int和long long纯C?
以下(C99和更新)代码想要计算一个方块,限制为与原始固定宽度类型相同的位数.
#include <stdint.h>
uint8_t sqr8( uint8_t x) { return x*x; }
uint16_t sqr16(uint16_t x) { return x*x; }
uint32_t sqr32(uint32_t x) { return x*x; }
uint64_t sqr64(uint64_t x) { return x*x; }
Run Code Online (Sandbox Code Playgroud)
问题是:取决于int大小,可以对提升为(signed)int的参数执行一些乘法,结果溢出(signed)int,因此就标准而言是未定义的结果; 并且可以想象错误的结果,特别是在(越来越罕见的)不使用二进制补码的机器上.
如果int是32位(分别为16位,64位,80位或128位),即发生对于sqr16(相应的sqr8,sqr32,sqr64)时x是0xFFFFF(相应的0xFF,0xFFFFFFFF,0xFFFFFFFFFFFFFFFF).4个功能都不能在C99下正式移植!!
C11或更高版本,或某些版本的C++,是否解决了这种不幸的情况?
一个简单,有效的解决方案是:
#include <stdint.h>
uint8_t sqr8( uint8_t x) { return 1u*x*x; }
uint16_t sqr16(uint16_t x) { return 1u*x*x; }
uint32_t sqr32(uint32_t …Run Code Online (Sandbox Code Playgroud) 在x86汇编中,当有符号整数上的add或sub操作溢出时,溢出标志置位,当无符号整数上的操作溢出时,置载标志置位.
然而,当谈到inc和dec说明,情况似乎有些不同.根据该网站,该inc指令根本不影响进位标志.
但我不能找到有关如何的任何信息inc和dec如果有的话,会影响溢出标志.
发生整数溢出时执行inc或dec设置溢出标志?对于有符号整数和无符号整数,这种行为是否相同?
============================= 编辑 ==================== =========
好的,基本上这里的共识是,就设置标志而言,INC和DEC应该与ADD和SUB的行为相同,但进位标志除外.这也是英特尔手册中的内容.
问题是,当涉及到无符号整数时,我实际上无法在实践中重现这种行为.
请考虑以下汇编代码(使用GCC内联汇编以便更轻松地打印结果.)
int8_t ovf = 0;
__asm__
(
"movb $-128, %%bh;"
"decb %%bh;"
"seto %b0;"
: "=g"(ovf)
:
: "%bh"
);
printf("Overflow flag: %d\n", ovf);
Run Code Online (Sandbox Code Playgroud)
这里我们递减一个带符号的8位值-128.由于-128是可能的最小值,溢出是不可避免的.正如所料,这打印出:Overflow flag: 1
但是当我们使用无符号值执行相同操作时,行为并不像我预期的那样:
int8_t ovf = 0;
__asm__
(
"movb $255, %%bh;"
"incb %%bh;"
"seto %b0;"
: "=g"(ovf)
:
: "%bh"
); …Run Code Online (Sandbox Code Playgroud) 如何检测D中的整数溢出?(检查携带标志?)
原始示例:
ubyte a = 100;
ubyte b = 200;
ubyte c = a + b;
// c can't represent 300; how to detect the overflow now?
Run Code Online (Sandbox Code Playgroud)
修改后的例子:
uint a = 2_000_000_000;
uint b = 3_000_000_000;
uint c = a + b;
// c can't represent 5_000_000_000; how to detect the overflow now?
Run Code Online (Sandbox Code Playgroud)
还有乘法和前/后增量.
为了好奇,我试图读取标志寄存器并以一种很好的方式将其打印出来.
我已经尝试使用gcc的asm关键字阅读它,但我无法让它工作.任何提示如何做到这一点?我正在运行Intel Core 2 Duo和Mac OS X.以下代码就是我所拥有的.我希望能告诉我是否发生溢出:
#include <stdio.h>
int main (void){
int a=10, b=0, bold=0;
printf("%d\n",b);
while(1){
a++;
__asm__ ("pushf\n\t"
"movl 4(%%esp), %%eax\n\t"
"movl %%eax , %0\n\t"
:"=r"(b)
:
:"%eax"
);
if(b!=bold){
printf("register changed \n %d\t to\t %d",bold , b);
}
bold = b;
}
}
Run Code Online (Sandbox Code Playgroud)
这给出了分段错误.当我运行gdb时,我得到了这个:
Program received signal EXC_BAD_ACCESS, Could not access memory.
Reason: KERN_INVALID_ADDRESS at address: 0x000000005fbfee5c
0x0000000100000eaf in main () at asm.c:9
9 asm ("pushf \n\t"
Run Code Online (Sandbox Code Playgroud) 在寻找对有符号和无符号整数算术进行溢出检查的函数时,我遇到了这个答案,它提供了很好的编译器内在函数,可以在 GCC 中进行检查数学。由于我当前编写的代码需要跨平台,因此我也需要 MSVC(Microsoft Visual Studio)编译器类似的东西。
是否存在或者我必须手动实现它?
我有一些针对某些财务应用程序的定点实现.它基本上是一个包含在类中的整数,它基于给定N的十进制数作为小数.该类是偏执的并检查溢出,但是当我在发布模式下运行我的测试时,它们都失败了,最后我创建了这个演示问题的最小例子:
#include <iostream>
#include <sstream>
template <typename T, typename U>
typename std::enable_if<std::is_convertible<U, std::string>::value, T>::type
FromString(U&& str)
{
std::stringstream ss;
ss << str;
T ret;
ss >> ret;
return ret;
}
int main()
{
int NewAccu=32;
int N=10;
using T = int64_t;
T l = 10;
T r = FromString<T>("1" + std::string(NewAccu - N, '0'));
if (l == 0 || r == 0) {
return 0;
}
T res = l * r;
std::cout << l << std::endl;
std::cout …Run Code Online (Sandbox Code Playgroud) 我很清楚64位有符号整数可以有多大? 多亏了这个问题及其简单明了的答案。
因此,据此,我可以说an unsigned int可以是2 ^ 64-1,而不是2 ^ 63-1吗?
2^63 - 1: 0111111111111111111111111111111111111111111111111111111111111111
2^64 - 1: 1111111111111111111111111111111111111111111111111111111111111111
Run Code Online (Sandbox Code Playgroud)
当且仅当我正确地获得它时,如何才能检测到未签名的溢出?以二进制补码表示的带符号整数的溢出将侵入最高位位置,并返回负数。但是这种未签名的情况如何?
c ×7
c++ ×5
assembly ×2
optimization ×2
x86 ×2
c++11 ×1
c99 ×1
d ×1
fixed-point ×1
flags ×1
int ×1
overflow ×1
visual-c++ ×1
x86-64 ×1