x 的值是多少,使得 x + 1 == x 和 x * 2 == x 都为真?

use*_*087 -4 c types ctf

标题基本上说明了一切。我的朋友给了我这个作为他在他正在做的一些 CTF 中解决的挑战。我想了一会儿,想不通。此外,INFINITY 不是一个有效的答案。谢谢。

Eri*_*hil 6

在 C 中发生这种情况的唯一方法是:

  • x是无穷大(+? 或 ??)(等效地,HUGE_VAL-HUGE_VAL在不支持无穷大的实现中)。
  • x 是 NaN,C 实现对 NaN 使用非 IEEE-754 行为。
  • x 与浮点表示中的无穷大相邻,并使用合适的有向舍入模式。
  • x+1x*2溢出以及 C 标准未定义的结果行为恰好将比较报告为真。
  • x是未初始化,因此不确定的,呈现出不同的值的两个出现xx+1 == x,使得比较结果为真,并且在x*2 == x任一同样呈现出不同的值或取值为零。
  • x 未初始化且具有自动存储持续时间且不采用其地址,因此该行为未由 C 标准定义,结果行为恰好将比较报告为真。

证明:

除了无穷大之外,这些陈述在实数中在数学上是错误的,因此这不能从实数行为中产生。所以它一定是由一些非实数行为引起的,例如溢出、包装、舍入、不确定值(在每次使用对象时可能不同)或未初始化的值。由于*被限制为具有算术操作数,我们只需要考虑算术类型。(在 C++ 中,可以定义一个类来使比较为真。)

对于有符号整数,具有完全定义的值非实数行为的发生+,并*仅在有溢出,所以这是一个可能性。

对于无符号整数,具有完全定义的值非实数行为的发生+,并*只有当包装。然后,通过包装模M,对于某个整数k,我们将有x +1 = x + kM,因此 1 = kM,这对于包装中使用的任何M都是不可能的。

对于_Bool类型,对可能值的详尽测试消除了它们。

对于浮点数,具有完全定义的值非实数行为的发生+,并*只与舍入,下溢和溢出,并与NaN的。NaN 从不按照 IEEE-754 规则进行比较,因此它们不能满足这一点,除了 C 标准不要求符合 IEEE-754 的事实,因此实现可以选择使比较为真。

x*2不会下溢,因为它会增加幅度。x+1可以使指数范围小于精度的反常浮点格式下溢,但这不会产生x+1 == x. x+1 == x可以通过四舍五入足够大来满足x,但x*2必须产生一个不是 的值x

那留下溢出。如果x是最大可表示的有限数(因此最大可表示数小于无穷大),并且舍入模式向下(向 ??)或向零,则x+1will yieldxx*2will yield x,因此比较产生真。类似地,最大的负可表示有限数将满足向上舍入(向 +?)或向零舍入的比较。


dxi*_*xiv 6

等式将适用于double x = HUGE_VAL;。从 C99 开始,引用cppreference.com

HUGE_VALFHUGE_VALHUGE_VALL宏扩展为正的浮点数常量表达式,其比较等于值在溢出的情况下,返回由浮点功能和操作员

示例代码:

#include <math.h>
#include <stdio.h>

int main() {
    double x = HUGE_VAL;
    printf("%d %d\n", x + 1 == x, 2 * x == x);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

输出

1 1
Run Code Online (Sandbox Code Playgroud)