对于每个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
表达式是x
值INT_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_MAX
为0
,对于所有其他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或更高),你可能会翻转符号。 想想0111111
与11111111
的十进制表示。 (显然不是32位,但这些想法仍然存在。)
如果你对它翻转的原因感到困惑,请查看两个补码。 这是一个非常聪明的整数实现,使得添加更容易。
编辑: INT_MAX + 1
是未定义的行为。 不一定会成为INT_MIN
。 但是,由于当x == INT_MAX
时x + 1
不一定> x
,那么答案显然是错误的!