2012-11-25 94 views
7

如何检测D中的整数溢出? (检查进位标志?)检测整数溢出

原来的例子:

ubyte a = 100; 
ubyte b = 200; 
ubyte c = a + b; 
// c can't represent 300; how to detect the overflow now? 

修订例如:

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? 
用乘法和前/后递增

也。

+2

看看相同的问题为C + + http://stackoverflow.com/questions/199333/best-way-to-detect-integer-overflow-in-cc –

+1

和大会http://stackoverflow.com/问题/ 3925528/x86-assembly-inc-and-dec-instruction-and-overflow-flag –

回答

5

你可以用一些内联汇编很容易地检查:

asm { jo overflowed; } // for checking signed types 
// or 
asm { jc overflowed; } // use this for checking unsigned types 

/* continue going */ 

return; 

overflowed: 

/* do whatever to handle it */ 

注意:你可能无法把这个功能,因为调用该函数可以重置标志。您可能希望在您感兴趣的操作之后将它内联。

可以使用运算符重载进行溢出的类型: http://arsdnet.net/dcode/ranged.d是一个示例。或者我认为模块是标准库中的std.bigint,通过提供任意大的整数类型来避免溢出。

+0

'jo' - *跳转溢出*?这看起来正是我所需要的。 –

+4

是的......但请注意,溢出并不会在无符号数上发生。考虑-1:11111111的二进制表示(为简洁起见,此处使用ubyte)。这与255相同。但处理器不知道或在意类型是否被签名,它只是看到了数字。 255 + 1 == -1 + 1 == 0.所以这将设置进位标志,但不是溢出标志。所以,如果你特别使用无符号数字,你会想要jc指令 - 如果进行跳转 - 相反。 –

+2

另一个潜在的问题是增量指令do * not *设置进位标志....并且编译器会优化a + = 1进入inc a,如果在编译时已知的话。所以你可以用+ b,因为它们是运行时的,但+ = 1或++可能会给asm检查带来令人惊讶的传递。 –

8

对于初学者,您提供的代码甚至不会编译,因为尺寸小于int的所有整数运算都使用int完成。所以a + b的结果是int,int不会隐含地转换为ubyte,因为这是一个缩小的转换。如果你想将它分配给c,那么你需要投它。

ubyte c = cast(ubyte)(a + b); 

现在,这显然是一个未经检查的转换,它会很高兴的东西44c(因为这是给定的100200值剧组的结果)。如果你想有一个检查转换,然后使用std.conv.to

ubyte c = to!ubyte(a + b); 

这将抛出一个ConvOverflowException(这是ConvException一个子类),因为结果将不会在请求的类型适合。

如果你想自己做一些事情,然后检查是否有溢出,那么你和C/C++基本上是一样的船只,并且没有进位标志或任何类型的东西。如果使用汇编代码检查,可能存在这样的事情。我不知道。但是这种语言当然不能提供这样的东西。 std.conv.to通过检查结果并查看它是否太大或太小(取决于参数的符号和类型)来计算出结果。

+0

如何添加像add一样的内在函数,也会返回溢出位? – Mehrdad

+0

@Mehrdad很可能有一些内部函数给你提供了与溢出有关的额外功能,但我对它们一无所知。这比我以前处理的级别要低,我不知道它们中有多少可以保证在所有体系结构中都有。 –

+0

示例代码只是一个模拟来说明我的问题。在闲暇时用'uint'替换'ubyte'。 –