我刚开始在学校学习 C,我正在努力掌握基本概念。
我们的作业有一个问题,
对于每个int x: x+1 > x
判断真假,真假推理,假反例。
我很困惑,因为我们被告知 int 类型是 32 位的,基本上这意味着整数是二进制格式。x+1 是在十进制值 1 上加 1 吗?
我刚开始在学校学习 C,我正在努力掌握基本概念。
我们的作业有一个问题,
对于每个int x: x+1 > x
判断真假,真假推理,假反例。
我很困惑,因为我们被告知 int 类型是 32 位的,基本上这意味着整数是二进制格式。x+1 是在十进制值 1 上加 1 吗?
x + 1 > x
是1
针对每个int
值,除了 value INT_MAX
whereINT_MAX + 1
是溢出,因此x + 1 > x
expression 是x
value of 的未定义行为INT_MAX
。
这实际上意味着编译器有权优化表达式:
x + 1 > x
经过
1
作为INT_MAX + 1
未定义的行为,编译器有权说对于这个特定的>
表达式INT_MAX + 1
是> INT_MAX
.
由于x + 1 > x
表达式是 的未定义行为,因此假设它是 false ( )x == INT_MAX
也是不安全的。x + 1 > x
0
请注意,如果x
声明为 anunsigned int
而不是 an int
,情况则完全不同。unsigned int
操作数永远不会溢出(它们环绕):UINT_MAX + 1 == 0
因此x + 1 > x
适用0
于所有其他x == UINT_MAX
值。1
x
现代编译器(如gcc
)通常会借此机会优化此表达式并将其替换为1
.
作为记录,已知服务器程序使用以下代码存在一些严重的安全问题:
if (ptr + offset < ptr)
该代码旨在触发安全条件,但编译器会优化if
语句(通过将表达式替换0
为正确)。
注意 32 位数字范围[-2147483648, 2147483647]
等于 [-2 31 , 2 31 -1 ]。
所以 for 表达式x+1 > x
为真[-2147483648, 2147483646]
但不是2147483647
因为添加到2147483647
32 位大小的数字会导致位溢出许多实现它使x + 1
但-2147483648
真正的行为在 C 标准中是未定义的。
所以,
x + 1 > x
仅 适用x
于[-2147483648, 2147483646]
x + 1 > x
, for x = 2147483647
is Undefined value 可能是 True 或 False 取决于编译器。如果编译器计算 =-2147483648
值将是 False。我不想给你答案,所以我会回答一个应该让你走上正轨的问题。
可以存储在 32 位有符号整数中的最大可能值是什么x + 1
时候?x
(2,147,483,647)
是的,x + 1 添加到十进制值 1。
这几乎在所有时间都是正确的。但是,如果您将 1 添加到 INT_MAX(即 2 15 - 1 或更大),您可能会翻转符号。想想0111111
vs的十进制表示11111111
。(显然不是 32 位,但想法成立。)
如果您对它翻转的原因感到困惑,请查看二进制补码。这是一个非常聪明的整数实现,使加法变得容易。
编辑:INT_MAX + 1
是未定义的行为。不一定变成INT_MIN
. 但既然x + 1
不一定是> x
when x == INT_MAX
,那么答案显然是错误的!