测试一个整数是否在容量范围内意味着您的代码将非常低效。例如,要添加 123,您需要进行 123 次增量和 123 次比较。
更好的方法是在执行操作之前确定操作是否会溢出。例如(仅适用于无符号整数):
if(sum <= ULLONG_MAX - a) {
sum += a;
} else {
/* It would have overflowed */
}
这是有效的,因为ULLONG_MAX - a
不能溢出。当您开始查看有符号整数时,它会成为一个更大的问题,因为它LLONG_MAX - a
可能会溢出(如果a
为负数),也LLONG_MIN - a
可能会溢出(如果a
为正数)。您需要测试两种方式:
if( ( a > 0) && (sum <= LLONG_MAX - a) {
sum += a;
} else if( ( a < 0) && (sum >= LLONG_MIN - a) {
sum += a;
} else if( a != 0) {
/* It would have overflowed */
}
一旦确定它是否会溢出,您就需要处理这种情况。例如; 如果您使用多个整数来表示一个更大的整数;然后(对于无符号整数):
if(sum_low <= ULLONG_MAX - a) {
sum_low += a;
} else {
sum_low -= (ULLONG_MAX - a) + 1;
sum_high++;
}
请注意,您必须非常小心,以避免在处理原始(避免)溢出时涉及的临时计算中发生意外溢出。
如果使用多个有符号整数来表示一个较大的有符号整数,那么溢出处理背后的逻辑就会变得复杂且容易出错。理论上是可以的;但是,最好将数字的符号分开,然后单独对无符号整数进行运算(或其逆运算-例如减去正数而不是添加负数);特别是如果您需要使用 3 个或更多整数来表示一个大整数,或者如果您需要更复杂的操作,例如乘法和除法。
当然,一旦您开始走这条路,您就可以有效地实现自己的“大数字”代码,并且可能应该找到/使用合适的库。
最后,如果您想将新数据类型视为原始数据类型(例如,并且能够执行类似的操作mydatatype a = 0;
),那么您就不走运了——C 不能以这种方式工作。从本质上讲,C 是美丽的,因为它不允许对试图阅读/理解代码的人隐藏复杂的事物;如果你想向毫无戒心的受害者隐藏重要信息,你就必须使用像 C++ 这样不那么漂亮的语言。;-)