对于每个int x:x + 1> x …这总是如此吗?

我刚刚开始在学校学习C,我正试图掌握基本概念。

我们的作业有一个问题,

对于每个int x: x+1 > x

确定是真还是假,如果是真的则给出推理,如果为假则给出反例。

我很困惑,因为我们被告知int类型是32位,基本上这意味着整数是二进制格式。 x + 1是否将1加1为十进制值?

 x + 1 > x 

每个int值为1 ,除了值INT_MAX ,其中INT_MAX + 1是溢出,因此x + 1 > x表达式是xINT_MAX未定义行为。

这实际上意味着编译器有权优化表达式:

 x + 1 > x 

通过

 1 

由于INT_MAX + 1是未定义的行为,编译器有权说这个特定的>表达式INT_MAX + 1 > INT_MAX

由于x + 1 > x表达式是x == INT_MAX未定义行为,因此假设x + 1 > x可以为false( 0 )也是不安全的。

请注意,如果x被声明为unsigned int而不是int则情况完全不同。 unsigned int操作数从不溢出(它们环绕): UINT_MAX + 1 == 0因此x + 1 > x对于x == UINT_MAX0 ,对于所有其他x值为x

现代编译器(如gcc )通常会利用这个机会来优化这个表达式并将其替换为1

为了记录,使用以下代码的已知服务器程序存在一些严重的安全问题:

  if (ptr + offset < ptr) 

该代码旨在触发安全条件,但编译器将优化if语句(通过将表达式替换为0 ),并允许攻击者在服务器程序中获得权限提升(通过打开可利用的缓冲区溢出的可能性,如果我没记错。)

32位数字范围的注释是[-2147483648, 2147483647] ,等于[-2 31,2 31 -1]。

所以对于表达式x+1 > x对于[-2147483648, 2147483646]是真的

但不适用于2147483647因为在32位大小的数字中添加2147483647导致位溢出许多实现它使x + 1-2147483648但实际行为在C标准中是未定义的。

所以,

  • x + 1 > x适用于[-2147483648, 2147483646] x
  • x + 1 > x ,对于x = 2147483647 ,未定义的值可能为True或False取决于编译器。 如果编译器计算= -2147483648值为False。

我不想给你答案,所以我会回答一个问题,让你走上正轨。

x是可以存储在32位有符号整数中的最大可能值时, x + 1是多少? (2,147,483,647)

是的,x + 1会将十进制值加1。

这几乎在所有时间都是如此。 但是如果你将1加到INT_MAX(即2 15 – 1或更高),你可能会翻转符号。 想想011111111111111的十进制表示。 (显然不是32位,但这些想法仍然存在。)

如果你对它翻转的原因感到困惑,请查看两个补码。 这是一个非常聪明的整数实现,使得添加更容易。

编辑: INT_MAX + 1是未定义的行为。 不一定会成为INT_MIN 。 但是,由于当x == INT_MAXx + 1不一定> x ,那么答案显然是错误的!