我刚开始在学校学习 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_MAXwhereINT_MAX + 1是溢出,因此x + 1 > xexpression 是xvalue of 的未定义行为INT_MAX。
这实际上意味着编译器有权优化表达式:
x + 1 > x
经过
1
作为INT_MAX + 1未定义的行为,编译器有权说对于这个特定的>表达式INT_MAX + 1是> INT_MAX.
由于x + 1 > x表达式是 的未定义行为,因此假设它是 false ( )x == INT_MAX也是不安全的。x + 1 > x0
请注意,如果x声明为 anunsigned int而不是 an int,情况则完全不同。unsigned int操作数永远不会溢出(它们环绕):UINT_MAX + 1 == 0因此x + 1 > x适用0于所有其他x == UINT_MAX值。1x
现代编译器(如gcc)通常会借此机会优化此表达式并将其替换为1.
作为记录,已知服务器程序使用以下代码存在一些严重的安全问题:
if (ptr + offset < ptr)
该代码旨在触发安全条件,但编译器会优化if语句(通过将表达式替换0为正确)。
注意 32 位数字范围[-2147483648, 2147483647]等于 [-2 31 , 2 31 -1 ]。
所以 for 表达式x+1 > x为真[-2147483648, 2147483646]
但不是2147483647因为添加到214748364732 位大小的数字会导致位溢出许多实现它使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 或更大),您可能会翻转符号。想想0111111vs的十进制表示11111111。(显然不是 32 位,但想法成立。)
如果您对它翻转的原因感到困惑,请查看二进制补码。这是一个非常聪明的整数实现,使加法变得容易。
编辑:INT_MAX + 1是未定义的行为。不一定变成INT_MIN. 但既然x + 1不一定是> xwhen x == INT_MAX,那么答案显然是错误的!