如何检测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?
还有乘法和前/后增量。
答案 0 :(得分:9)
对于初学者来说,你提供的代码甚至都不会编译,因为所有大小都小于int
的整数数学都是用int
完成的。因此,a + b
的结果为int
,int
不会隐式转换为ubyte
,因为这是一个缩小的转化。如果您想将其分配给c
,那么您需要投射它。
ubyte c = cast(ubyte)(a + b);
现在,这显然是一种未经检查的转换,它会很高兴地将44
填入c
(因为这是给定100
和200
值的广告的结果)。如果您需要检查转化,请使用std.conv.to
:
ubyte c = to!ubyte(a + b);
这将抛出ConvOverflowException
(ConvException
的子类),因为结果将不适合所请求的类型。
如果你想自己做演员,然后检查是否有溢出,那么你和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,通过提供任意大的整数类型来避免溢出。