Jes*_*uhl 30
您无法检测到签名int溢出。您必须编写代码来避免它。
有符号的int溢出是未定义的行为,如果程序中存在该溢出,则该程序无效,并且不需要编译器生成任何特定的行为。
abh*_*ora 18
您可以预测,signed int overflow但是在总和为时已晚之后尝试检测它。在进行签名添加之前,必须测试可能的溢出。
求和后不可能通过测试未定义的行为来避免它。如果添加溢出,则已经存在未定义的行为。
如果是我,我会做这样的事情:
#include <limits.h>
int safe_add(int a, int b)
{
if (a >= 0) {
if (b > (INT_MAX - a)) {
/* handle overflow */
}
} else {
if (b < (INT_MIN - a)) {
/* handle underflow */
}
}
return a + b;
}
Run Code Online (Sandbox Code Playgroud)
有关更多信息,请参考本文。您还可以在同一篇文章中找到为什么无符号整数溢出不是未定义的行为以及可能是可移植性的问题。
编辑:
GCC和其他编译器有一些规定来检测溢出。例如,GCC具有以下内置函数允许执行简单的算术运算以及检查运算是否溢出。
bool __builtin_add_overflow (type1 a, type2 b, type3 *res)
bool __builtin_sadd_overflow (int a, int b, int *res)
bool __builtin_saddl_overflow (long int a, long int b, long int *res)
bool __builtin_saddll_overflow (long long int a, long long int b, long long int *res)
bool __builtin_uadd_overflow (unsigned int a, unsigned int b, unsigned int *res)
bool __builtin_uaddl_overflow (unsigned long int a, unsigned long int b, unsigned long int *res)
bool __builtin_uaddll_overflow (unsigned long long int a, unsigned long long int b, unsigned long long int *res)
Run Code Online (Sandbox Code Playgroud)
访问此链接。
编辑:
关于某人提出的问题
我认为,解释为什么有符号的int溢出未定义,而无符号的却不是这样,这将是非常有益和有益的。
答案取决于编译器的实现。大多数C实现(编译器)使用的最简单的溢出行为就是使用它使用的整数表示形式。
在实践中,签署值表示可能会有所不同(根据实现): ,one's complement,。two's complement sign-magnitude对于无符号类型,标准没有理由允许变化,因为只有一个明显的binary representation(标准仅允许二进制表示)。
在执行加法之前,必须先测试带符号的操作数。这是在所有情况下均进行2次比较的安全加法函数:
#include <limits.h>
int safe_add(int a, int b) {
if (a >= 0) {
if (b > INT_MAX - a) {
/* handle overflow */
} else {
return a + b;
}
} else {
if (b < INT_MIN - a) {
/* handle negative overflow */
} else {
return a + b;
}
}
}
Run Code Online (Sandbox Code Playgroud)
如果long long已知类型的范围大于type int,则可以使用这种方法,这可能会更快:
#include <limits.h>
int safe_add(int a, int b) {
long long res = (long long)a + b;
if (res > INT_MAX || res < INT_MIN) {
/* handle overflow */
} else {
return (int)res;
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3774 次 |
| 最近记录: |