C 没有得到整数溢出

C 没有得到整数溢出,c,overflow,signed-integer,C,Overflow,Signed Integer,假设我想打印一些值。我假设如果我的有符号变量超过了TMin和TMax(在本例中,使用4字节int、0x7FFFFFFF作为TMax和0x8000000作为TMin),我会得到整数溢出,但在这些示例中,我没有得到预期的结果(在注释中解释): 首先,让我告诉你,(有符号)整数溢出调用 在这种情况下,任何事情都可能发生。您既不能信任代码的输出,也不能对其进行推理 只是想澄清一下,甚至 printf("2- overflow test: %d\n", 0x80000000-1 ); 是UB。虽然0x8

假设我想打印一些值。我假设如果我的有符号变量超过了
TMin
TMax
(在本例中,使用4字节int、
0x7FFFFFFF
作为
TMax
0x8000000
作为
TMin
),我会得到整数溢出,但在这些示例中,我没有得到预期的结果(在注释中解释):


首先,让我告诉你,(有符号)整数溢出调用

在这种情况下,任何事情都可能发生。您既不能信任代码的输出,也不能对其进行推理

只是想澄清一下,甚至

printf("2- overflow test: %d\n", 0x80000000-1 );
是UB。虽然
0x80000000-1
无符号的
并且本身不是溢出,但使用
%d
将导致类型不匹配,从技术上讲,这将导致UB

关于未定义的行为,参见附录§J.2中的C11

转换为整数类型或从整数类型转换生成的值超出了可以修改的范围 代表


尝试调用整数溢出是未定义的行为。根据标准,在这种情况下,任何事情都可能发生,包括外观上的非溢出。这种输出是无趣的和无关的

可能是编译器优化了它。这可能是因为你的系统拒绝以这种方式使用,也可能是因为一袋大米落在中国造成了蝴蝶效应,导致了这种情况。这里所发生的一切都不明确


也可能是系统决定其整数更大。在c语言中,只有整数大小的下限(2字节)是强制要求的(标准计算机通常至少有4字节)。您的系统可能有8个字节的整数,甚至更大的整数。

OP并不总是遇到有符号整数溢出-这是一种未定义的行为

以下是无符号数学,因为
0x8000000
可能是无符号整数。十六进制常量的类型首先适合它们
int、unsigned、long、unsigned long、…

printf("2- overflow test: %d\n", 0x80000000-1 );
0x8000000-1
是一种无符号类型,因为
0x8000000
首先适用于无符号类型,很可能是
unsigned
,其值为
2147483648u
<代码>2147483648u-1-->
2147483647u

0x7FFFFFFF+1
是有符号类型,因为
0x7fffff
首先适合有符号类型,很可能
int
的值为
int\u MAX

int
+
int
-->
int
int\u MAX+1
-->溢出



OP表示,“0x8000000作为Tmin”肯定是一种误解。在C语言中,对于32位的
int/无符号
0x8000000
是一个十六进制常量,其值为
2147483648
。对于OP,Tmin更可能是
-INT\u MAX-1

C对于数值异常有点不一致

你可以做一些几乎总是会引起问题的事情。如果除以0,程序通常会严重崩溃,就像访问了无效指针一样

你可以做一些事情,保证不会造成问题。如果你说

unsigned int i = UINT_MAX;
然后再加上1,就保证了0

还有一些行为是未定义或未指定的。有符号整数溢出就是其中之一。严格地说,它是未定义的(任何事情都可能发生,你不能依赖它)。在实践中,大多数计算机都会像无符号算术一样安静地运行


现在,我所说的一切都是关于程序的运行时行为的,但是在这个问题发布的代码片段中,所有的算法都发生在编译时。编译时算法主要根据与运行时相同的规则进行操作,但并不总是这样。现代编译器倾向于就有问题的编译时算法向您发出警告(我的gcc副本会对发布的片段发出三条警告),但并不总是如此。

第一条-您使用的是带符号的格式。Second-literal在运行时进行计算,因此没有溢出。无论如何,签名溢出是未定义的。@TNW像
0x7FFFFFFF+1
这样的表达式是在编译时计算的。@TNW那么为什么#1的行为与#2不同(因为语法在我看来是一样的)@HoomanYar为什么不呢?它未定义的行为,也就是字面上未定义的行为。在这一点上,任何事情都可能发生。@HoomanYar,正如答案所说:这是未定义的行为。因此,它不必做任何您可能期望的事情,甚至不必保持一致。因此,如果int溢出几乎是随机发生的,我们如何确定随机输入是否会发生溢出?@HoomanYar,方法是确保您的值不超过整数中允许的值。溢出仅在超过该值时发生。因此,如果你的整数是32位的(很可能是32位),只要有符号整数的值不超过2^32-1或不超过2^32/2-1,有符号整数的值不低于-2^32“只有整数大小的下限(4字节)在c中是强制的。”-2字节,当然可以?@HoomanYar:除非你的系统中有某种真正的白噪声源,否则任何事情都不会随机发生。请仔细思考未定义的含义,就像在未定义的行为中一样。为鼻守护程序、你的计算机跳出窗口自杀等做好准备。@Magisch:大多数出售的系统都有16位
int
。标准允许填充位。有符号的
long
signed
char`呢?等(很抱歉吹毛求疵。请想一想更一般的;-)@Olaf将其改为“有符号整数类型”会更好吗?@Olaf我指的是§6.2.5/17。可以吗?:)为什么不引用(并链接)标准呢。例如,见3.4.3。“有符号整数”有什么问题?;-)@Olaf现在更新了。请检查一次。一旦您调用UB,所有赌注都将被取消,无论其他赌注是否正确。IOW:UB是致命的。@Olaf OP的代码注释“为什么我在这里没有得到整数溢出”肯定是由于缺少编译时警告而被发现的
unsigned int i = UINT_MAX;