如何在C语言中检测整数溢出
我们知道当数字变大时,CPython会将整数提升为长整数(允许任意精度的算术) 如何在纯C中检测如何在C语言中检测整数溢出,c,overflow,C,Overflow,我们知道当数字变大时,CPython会将整数提升为长整数(允许任意精度的算术) 如何在纯C中检测int和long溢出?您无法检测有符号int溢出。您必须编写代码来避免它 有符号整数溢出是未定义的行为,如果它存在于您的程序中,则该程序无效,并且不需要编译器生成任何特定行为。您无法检测有符号的int溢出。您必须编写代码来避免它 有符号整数溢出是未定义的行为,如果它存在于您的程序中,则该程序无效,并且编译器不需要生成任何特定行为。您可以预测有符号整数溢出,但尝试在求和后检测它为时已晚。在执行签名加法之
int
和long
溢出?您无法检测有符号int
溢出。您必须编写代码来避免它
有符号整数溢出是未定义的行为,如果它存在于您的程序中,则该程序无效,并且不需要编译器生成任何特定行为。您无法检测有符号的int
溢出。您必须编写代码来避免它
有符号整数溢出是未定义的行为,如果它存在于您的程序中,则该程序无效,并且编译器不需要生成任何特定行为。您可以预测有符号整数溢出,但尝试在求和后检测它为时已晚。在执行签名加法之前,必须测试可能的溢出 在求和后通过测试来避免未定义的行为是不可能的。如果添加溢出,则已经存在未定义的行为 如果是我,我会这样做:
#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;
}
访问这个
编辑:
关于某人提出的问题
我认为,解释为什么有符号整数溢出未定义,而无符号溢出显然未定义,这将是一件非常好的事情 答案取决于编译器的实现。大多数C实现(编译器)只是使用它所使用的整数表示法来实现最容易实现的溢出行为
实际上,有符号值的表示可能不同(根据实现):
一个补码
,两个补码
,符号幅度
。对于无符号类型,标准没有理由允许变化,因为只有一种明显的二进制表示法
(标准只允许二进制表示法)。您可以预测有符号整数溢出
,但尝试在求和后检测它为时已晚。在执行签名加法之前,必须测试可能的溢出
在求和后通过测试来避免未定义的行为是不可能的。如果添加溢出,则已经存在未定义的行为
如果是我,我会这样做:
#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;
}
访问这个
编辑:
关于某人提出的问题
我认为,解释为什么有符号整数溢出未定义,而无符号溢出显然未定义,这将是一件非常好的事情 答案取决于编译器的实现。大多数C实现(编译器)只是使用它所使用的整数表示法来实现最容易实现的溢出行为
实际上,有符号值的表示可能不同(根据实现):
一个补码
,两个补码
,符号幅度
。对于无符号类型,标准没有理由允许变化,因为只有一种明显的二进制表示形式
(标准仅允许二进制表示形式)。在执行加法之前,必须测试有符号操作数。这是一个安全的加法函数,在所有情况下都有两个比较:
#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;
}
}
}
在执行加法之前,必须测试有符号操作数。这是一个安全的加法函数,在所有情况下都有两个比较:
#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;
}
}
}
这是非常棘手的,因为您无法添加两个数字并检查值是否高于某个阈值(因为有符号整数算术溢出等等)。一个简单的解决方案可能是检查
x
(要检查的值)是否高于特定阈值,或者添加一个值是否高于阈值。如果是这样,并且您要添加的另一个数字大于1,那么您就出现了溢出情况。吹毛求疵,但是,是CPython 2.7做到了这一点。CPython 3不会“升级”任何内容,即使在内部只有一种类型。根据您对值的处理方式(add/sub/mul/div/…),会有很多重复项(add/sub/mul/div/…),再添加1。这非常棘手,因为您无法添加两个数字并检查值是否高于某个阈值(因为有符号整数算术溢出等). 一个简单的解决方案可能是检查x
(要检查的值)是否高于特定阈值,或者添加一个值是否高于阈值。如果是这样,并且您要添加的另一个数字大于1,那么您就出现了溢出情况。吹毛求疵,但是,是CPython 2.7做到了这一点。CPython 3不会“升级”任何东西,即使在内部只有一种类型。根据您想对值执行的操作(add/sub/mul/div/…),会有很多重复项,再添加1个,您可以在进行计算之前检查输入值以防止溢出。我想,解释一下为什么有符号整数溢出未定义,而无符号溢出显然没有定义,这将是一件非常有益的事情。@Heteperfan这是因为语言标准是这么说的。@sneftel这是一个缺乏权威来源的权威论点,尽管它可能是正确的。最重要的是,一旦人们开始理解语言,标准对他们来说就更有意义,这可能是他们首先访问stackoverflow的原因。@Heteperfan解释了标准按原样编写的原因,在很大程度上超出了堆栈溢出的范围。在进行计算之前,您可以检查输入值以防止溢出。我认为,解释为什么未定义有符号整数溢出是一件非常有益的事情,然而unsigned显然不是…@heteperfan,这是因为语言标准是这么说的。@snetel这是一个缺乏权威来源的权威论点,轻视它可能是正确的。最重要的是,一旦人们开始理解,标准对他们来说就更有意义了