检测整数溢出

时间:2012-11-25 00:15:19

标签: int d

如何检测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 个答案:

答案 0 :(得分:9)

对于初学者来说,你提供的代码甚至都不会编译,因为所有大小都小于int的整数数学都是用int完成的。因此,a + b的结果为intint不会隐式转换为ubyte,因为这是一个缩小的转化。如果您想将其分配给c,那么您需要投射它。

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

现在,这显然是一种未经检查的转换,它会很高兴地将44填入c(因为这是给定100200值的广告的结果)。如果您需要检查转化,请使用std.conv.to

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

这将抛出ConvOverflowExceptionConvException的子类),因为结果将不适合所请求的类型。

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

答案 1 :(得分:7)

您可以使用内联汇编轻松检查它:

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,通过提供任意大的整数类型来避免溢出。