在执行数学运算后,例如,将两个整数相乘,是否可以使用 C++ 访问 CPU 中的溢出标志寄存器?如果不是还有什么其他快速检查溢出的方法?
5 回答
不,一般是不可能的。有些 CPU 甚至没有这样的标志(例如 MIPS)。
其中一条评论中提供的链接将为您提供有关如何进行溢出检查的想法。
请记住,在 C 和 C++ 中,有符号整数溢出会导致未定义的行为,并且法律上您不能在事后执行溢出检查。您要么需要使用无符号算术,要么在算术运算之前进行检查。
我建议在每个适当的情况下阅读此书。从 用 C++ 优化软件-
整数溢出是另一个安全问题。官方 C 标准说有符号整数在溢出的情况下的行为是“未定义的”。这允许编译器忽略溢出或假设它不会发生。在 Gnu 编译器的情况下,没有发生有符号整数溢出的假设具有不幸的结果,它允许编译器优化溢出检查。有许多可能的补救措施来解决这个问题:(1) 在溢出发生之前检查溢出,(2) 使用无符号整数 - 它们保证可以回绕,(3) 使用 option 捕获整数溢出
-ftrapv
,但这是非常低效的, (4) 使用 option 获得此类优化的编译器警告-Wstrict-overflow=2
,或 (5) 使用 option 明确定义溢出行为-fwrapv
或-fno-strict-overflow
。
您必须执行该操作并检查内联汇编中的溢出位。您可以这样做并在溢出时跳转到标签,或者(更普遍但效率较低)在溢出时设置变量。
没有。最好的方法在这里提前检查
如果不是还有什么其他快速检查溢出的方法?
如果您需要在操作后进行测试,您可以使用浮点表示(双精度) - 每个 32 位整数都可以完全表示为浮点数。如果您所针对的所有机器都支持 IEEE(如果您不必考虑大型机,可能就是这种情况),您可以只执行操作,然后在结果上使用 isfinite 或 isinf。快速(就程序员的努力而言)方式是:IEEE 浮点算术标准(IEEE 754)定义了五个异常,每个异常都返回一个默认值并具有相应的状态标志(在某些下溢情况下除外)发生异常时引发。五个可能的例外是:
- 无效运算:数学上未定义,例如,负数的平方根。默认情况下,返回 qNaN。
- 除以零:对有限操作数的运算给出精确的无限结果,例如 1/0 或 log(0)。默认情况下,返回±无穷大。
- 溢出:结果太大而无法正确表示(即,其具有无限指数范围的指数将大于 emax)。默认情况下,对于最近舍入模式返回 ±infinity(并遵循有向舍入模式的舍入规则)。
- 下溢:结果非常小(超出正常范围)且不精确。默认情况下,返回次正规或零(遵循舍入规则)。
- 不精确:精确(即未四舍五入的)结果不能精确表示。默认情况下,返回正确舍入的结果。
这可能不是您想要做的,原因有两个:
- 不是每个 CPU 都有溢出标志
- 使用 C++ 实际上没有办法访问溢出标志
人们之前发布的溢出检查提示可能很有用。
如果您真的想非常快速地编写将两个整数相乘并检查溢出标志的代码,您将不得不使用汇编。如果您想要一些 x86 的示例,请询问