8

如何检测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?

还具有乘法和前/后增量。

4

2 回答 2

9

对于初学者,您提供的代码甚至无法编译,因为所有大小小于int的整数数学都是使用int. 所以a + bis的结果int,并且int不会隐式转换为ubyte,因为这是一个缩小转换。如果要将其分配给c,则需要对其进行强制转换。

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

现在,这显然是一个未经检查的转换,它会很高兴地44填入c(因为这是给定100and值的强制转换的结果200)。如果您想要检查转换,请使用std.conv.to

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

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

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

于 2012-11-25T04:13:30.110 回答
7

2021 年更新:此技术仅在您使用没有优化的 dmd 时才有效(即使那样做其他方法可能更好)。要在更多情况下工作,您可以在内联汇编中执行所有操作(顺便说一句,这可能会破坏优化器),或者使用core.checkedint具有ref bool overflowed可以在操作结束时检查的参数的操作(这也是内联友好的顺便说一句再次用于优化器)。

原帖如下:

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

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

于 2012-11-26T01:09:37.633 回答