如何检测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)
还有乘法和前/后增量.
对于初学者来说,你提供的代码甚至都不会编译,因为大小小于的所有整数数学都是用来int完成的int.因此,结果a + b是int,并且int不会隐式转换为ubyte,因为这是一个缩小的转换.如果你想分配它c,那么你需要投射它.
ubyte c = cast(ubyte)(a + b);
Run Code Online (Sandbox Code Playgroud)
现在,这显然是一个未经检查的转换,它会很高兴的东西44到c(因为这是给定的值塑像的结果100和200).如果您想要检查转换,请使用std.conv.to:
ubyte c = to!ubyte(a + b);
Run Code Online (Sandbox Code Playgroud)
这将抛出一个ConvOverflowException(它的子类ConvException),因为结果将不适合所请求的类型.
如果你想自己进行投射,然后检查是否有溢出,那么你基本上和C/C++一样,并且没有进位标志或任何类似的东西.如果您使用汇编代码检查,可能存在这种情况.我不知道.但是这种语言肯定不会提供类似的东西.std.conv.to通过检查结果并查看它是否太大或太小(取决于参数的符号和类型)来计算出来.
您可以使用一些内联汇编轻松检查它:
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 */
Run Code Online (Sandbox Code Playgroud)
注意:您可能无法将其放入函数中,因为调用该函数可以重置该标志.您希望在您感兴趣的操作之后立即将其放入内联.
可以创建一个使用运算符重载的类型来抛出溢出:http: //arsdnet.net/dcode/ranged.d就是一个例子.或者我认为标准库中的模块是std.bigint,通过提供任意大的整数类型来避免溢出.