说我想要打印一些值。如果我的签名变量超过TMin
和TMax
(在这种情况下,使用4字节int,0x7FFFFFFF
作为Tmax
和{{},我假设我应该得到整数溢出1}}作为0x80000000
)但在这些例子中我没有达到我的期望(在评论中解释):
Tmin
答案 0 :(得分:2)
首先,让我告诉你,(签名)整数溢出调用undefined behavior。
在那种情况下,任何事情都可能发生。您既不能信任也不能推断出具有UB的代码的输出。
只是澄清,甚至
printf("2- overflow test: %d\n", 0x80000000-1 );
是UB。虽然0x80000000-1
是unsigned
而不是溢出,但使用%d
会导致类型不匹配,从技术上讲会导致UB。
关于未定义的行为,来自C11
,附件§J.2,
转换为整数类型或从整数类型转换会产生超出范围的值 表示。
答案 1 :(得分:1)
尝试调用整数溢出是未定义的行为。按照标准,在这种情况下,任何事情,包括向外出现的非溢出都可能发生。这产生的结果是无趣和无关紧要的。
可能是您的编译器优化了它。可能是你的系统拒绝以这种方式使用,可能是因为一袋米饭落在中国造成了导致这种情况的蝴蝶效应。它的任何东西都定义了那里发生的事情。
也可能是您的系统决定其整数更大。在c中仅强制要求整数大小的下限(2字节)(标准计算机通常至少为4)。你的系统可能有8个字节的整数,甚至更大的整数。
答案 2 :(得分:1)
OP并不总是遇到有符号整数溢出 - 这是未定义的行为。
以下是无符号数学,因为0x80000000
可能是无符号整数。十六进制常量的类型首先适合它们int, unsigned, long, unsigned long, ...
printf("2- overflow test: %d\n", 0x80000000-1 );
0x80000000-1
是无符号类型,因为0x80000000
首先适合无符号类型,可能unsigned
的值为2147483648u
。 2147483648u - 1
- > 2147483647u
。
0x7FFFFFFF+1
是签名类型,0x7FFFFFFF
首先适用于签名类型,可能int
的值为INT_MAX
。
int
+ int
- > int
和 INT_MAX + 1
- >溢出。
OP表示" 0x80000000为Tmin"当然是一种误解。在C中,使用32位int/unsigned
,0x80000000
是十六进制常量,其值为2147483648
。对于OP,Tmin更可能是-INT_MAX - 1
。
答案 3 :(得分:1)
C与数字异常有点不一致。
您可以做的一些事情几乎总是会导致问题。如果除以0,您的程序通常会很难崩溃,就像您访问了无效指针一样。
您可以做的一些事情可以保证不会导致问题。如果你说
unsigned int i = UINT_MAX;
然后加1,它保证回绕到0。
然后有许多行为未定义或未指定的行为。有符号整数溢出就是其中之一。严格来说,它是未定义的(任何事情都可能发生,你不能依赖它)。实际上,大多数计算机都会安静地环绕,就像无符号算术一样。
现在,我所说的一切都是关于程序的运行时行为,但是在这个问题的发布代码片段中,所有算法都在编译时发生。编译时算术主要根据与运行时相同的规则运行,但并非总是如此。现代编译器倾向于警告你有问题的编译时算术(我的gcc副本为发布的片段发出三个警告),但并非总是如此。