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

问题描述

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

解决方法

在 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,我们将 x+1 = x+kM 用于某个整数 >k,所以 1 = kM,这对于任何用于包装的 M 都是不可能的。

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

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

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

这会导致溢出。如果 x 是最大可表示的有限数(因此是小于无穷大的最大可表示数),并且舍入模式向下(向 -∞)或向零,则 x+1 将产生 {{1 }} 和 x 将产生 x*2,所以比较产生真。类似地,最大的负可表示有限数将满足向上舍入(向+∞)或向零舍入的比较。

,

等式对 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;
}

Output

1 1
,

使用 C 预处理器求解 x

#include <stdio.h>

int main() {

#define x  1,1

    if (x + 1 == x)
        printf("x + 1 == x is true\n");

    if (x * 2 == x)
        printf("x * 2 == x is true\n");

    printf("x     = %d\n",x);
    printf("x + 1 = %d\n",x + 1);
    printf("x * 2 = %d\n",x * 2);

    return 0;
}

输出(省略警告:):

x + 1 == x is true
x * 2 == x is true
x     = 1
x + 1 = 1
x * 2 = 1

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...