没有得到整数溢出

时间:2016-02-01 19:58:43

标签: c overflow signed-integer

说我想要打印一些值。如果我的签名变量超过TMinTMax(在这种情况下,使用4字节int,0x7FFFFFFF作为Tmax和{{},我假设我应该得到整数溢出1}}作为0x80000000)但在这些例子中我没有达到我的期望(在评论中解释):

Tmin

4 个答案:

答案 0 :(得分:2)

首先,让我告诉你,(签名)整数溢出调用undefined behavior

在那种情况下,任何事情都可能发生。您既不能信任也不能推断出具有UB的代码的输出。

只是澄清,甚至

printf("2- overflow test: %d\n", 0x80000000-1 );

是UB。虽然0x80000000-1unsigned而不是溢出,但使用%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的值为2147483648u2147483648u - 1 - > 2147483647u

0x7FFFFFFF+1是签名类型,0x7FFFFFFF首先适用于签名类型,可能int的值为INT_MAX
int + int - > int INT_MAX + 1 - >溢出。

OP表示" 0x80000000为Tmin"当然是一种误解。在C中,使用32位int/unsigned0x80000000是十六进制常量,其值为2147483648。对于OP,Tmin更可能是-INT_MAX - 1

答案 3 :(得分:1)

C与数字异常有点不一致。

您可以做的一些事情几乎总是会导致问题。如果除以0,您的程序通常会很难崩溃,就像您访问了无效指针一样。

您可以做的一些事情可以保证不会导致问题。如果你说

unsigned int i = UINT_MAX;

然后加1,它保证回绕到0。

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

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