与“;算术运算导致溢出“;

本文关键字:溢出 算术运算 | 更新日期: 2023-09-27 18:23:46

我有这个表达式

 long balance = (long)answer.Find(DppGlobals.TAG_TI_BALANCE).Get_QWORD();

这引发了溢出的异常。右侧的值为无符号类型,其值为:18446744073708240732。

如何避免此异常,请使用unchecked

PS等价的C++实现返回了余额=-1310984,我这里也需要相同的值。

为什么会有这样的例外?


通过现在也在C#端使用unchecked,我得到-1310984。有人能告诉我,我是不是不知怎么丢失了数据?

与“;算术运算导致溢出“;

使用uncheck也会裁剪您的值,但不会出现异常,您会得到错误的数字。我认为你会改变你的代码,而不是掩盖你的异常。

long balance = (unchecked))(long)answer.Find(DppGlobals.TAG_TI_BALANCE).Get_QWORD());

为什么会有这样的例外

你犯了一个错误是件好事。因为如果你在一切都是数字的领域工作,你可能会犯错误,不理解这一点。因此,运行时将向您显示您的eror

考虑到注释,听起来您只需要使用未检查的算术,但您应该注意API中ulong的使用。如果你的目标是只传播8个字节的数据,并根据上下文将其解释为无符号整数或有符号整数,那么你就可以了——只要没有什么能以"错误"的形式对其进行运算。

理解为什么会发生这种情况很重要,用小数字来解释也容易得多。我将使用bytesbyte作为示例。byte的范围为0到255(包括0到255)。sbyte的范围是-128到127,包括-128到-127。两者都可以存储256个不同的值。没问题。

现在,使用未检查的转换,可以说:

byte a = GetByteFromSomewhere();
sbyte b = (sbyte) a;
StoreSByteSomewhere(b);
...
sbyte b = GetSByteFromStorage();
byte a = (byte) b;

如果这就是你所做的全部,那没关系。-1的byte值将变成255的sbyte值,反之亦然——基本上,它只是以不同的方式解释相同的比特模式。

但是,如果在将值作为"错误"类型处理时对其执行其他操作,则可能会得到意外的答案。例如,考虑"除以3"。如果你把-9除以3,你得到-3,对吧?而如果你有:

byte original = -9;
sbyte converted = (sbyte) original;
sbyte divided = converted / 3;
byte result = (byte) divided;

然后你得到的结果是-2,而不是-3,这是由于算术的工作方式。

现在,未检查的转换到此为止。当您进行检查转换时,它不仅仅解释位,而是将值视为数字。例如:

// In a checked context...
byte a = 128;
sbyte b = (sbyte) a; // Bang! Exception

这是因为128(作为一个数字)在sbyte的范围之外。这就是你的情况——号码18446744073708240732在long的范围之外,所以你得到了一个例外。已检查的转换将其视为可以进行范围检查的数字,而不是未检查的转换,只是将位重新解释为long(这会导致您想要的负数)。