int y = -2147483648;
int z = unchecked(y / -1);
第二行代码会抛出一个OverflowException异常。使用unchecked关键字不应该可以预防这种情况吗?例如:
int y = -2147483648;
int z = unchecked(y * 2);
不会引发异常。
int y = -2147483648;
int z = unchecked(y / -1);
第二行代码会抛出一个OverflowException异常。使用unchecked关键字不应该可以预防这种情况吗?int y = -2147483648;
int z = unchecked(y * 2);
不会引发异常。
C和C++语言规范通过将其定义为未定义行为而升级了赌注。这可能真的很丑陋,例如使用gcc或g ++编译器(通常是使用MinGW工具链)。该工具链对于SEH的运行时支持并不完善,它会吞下异常并允许处理器重新启动除法指令。程序挂起,使处理器不断生成#DE陷阱。将除法转换为传说中的Halt and Catch Fire指令 :)
unchecked
的要求。事实上,当处理器抛出错误时,C#重新抛出该错误并不能真正解释任何问题。 - Servyunchecked
的整个意义在于当整数操作溢出时不会抛出溢出异常,而是进行包装。 - Servyneg
对于 -2147483648 的结果并不是垃圾值,实际上它是 +2147483648(当被解释为无符号数时)。 - haroldC# 4规范的第7.72节(除法运算符)指出:
如果左操作数是最小表示的int或long值,右操作数为-1,则会发生溢出。在已检查的上下文中[...]。在未检查的上下文中,实现定义为抛出System.ArithmeticException(或其子类)或溢出未报告并将结果值作为左操作数的值。
因此,在未检查的上下文中,这会引发异常实际上并不是错误,因为行为是实现定义的。
int
或long
值,右操作数是-1
,则会发生溢出。在此情况下,无论操作是在“checked”还是“unchecked”上下文中发生,都将始终抛出System.OverflowException
异常。 - Dmitry根据C# 语言规范 5.0第7.8.2节,我们有以下情况:
7.8.2 除法运算符 对于形如 x / y 的操作,应用二元运算符重载解析(§7.3.4)以选择特定的运算符实现。操作数转换为所选运算符的参数类型,并且结果类型是运算符的返回类型。下面列出了预定义的除法运算符。所有运算符都计算 x 和 y 的商。 整数除法: int operator /(int x, int y); uint operator /(uint x, uint y); long operator /(long x, long y); ulong operator /(ulong x, ulong y); 如果右操作数的值为零,则抛出 System.DivideByZeroException 异常。该除法将结果向零舍入。因此,结果的绝对值是小于或等于两个操作数商的最大可能整数。当两个操作数具有相同符号时,结果为零或正;当两个操作数具有相反符号时,结果为零或负。如果左操作数是最小可表示的 int 或 long 值,而右操作数是 -1,则会发生溢出。在已检查的上下文中,这会导致抛出 System.ArithmeticException(或其子类) 。在未经检查的上下文中,它是实现定义的,即抛出 System.ArithmeticException(或其子类) 或溢出不报告,其结果值为左操作数的值。