如何解决x 的值是多少,使得 x + 1 == x 和 x * 2 == x 都为真?
标题基本上说明了一切。我的朋友给了我这个作为他在他正在做的一些 CTF 中解决的挑战。我想了一会儿,想不通。此外,INFINITY 不是一个有效的答案。谢谢。
解决方法
在 C 中发生这种情况的唯一方法是:
-
x
是无穷大(+∞ 或 −∞)(等效于不支持无穷大的实现中的HUGE_VAL
或-HUGE_VAL
)。 -
x
是 NaN,C 实现对 NaN 使用非 IEEE-754 行为。 -
x
与浮点表示中的无穷大相邻,并且使用了合适的有向舍入模式。 -
x+1
和x*2
溢出,C 标准未定义的结果行为恰好将比较报告为真。 -
x
未初始化,因此不确定,并在x
中x+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 == x
。 x+1 == x
可以通过对足够大的 x
进行四舍五入来满足,但是 x*2
必须产生除 x
之外的值。
这会导致溢出。如果 x
是最大可表示的有限数(因此是小于无穷大的最大可表示数),并且舍入模式向下(向 -∞)或向零,则 x+1
将产生 {{1 }} 和 x
将产生 x*2
,所以比较产生真。类似地,最大的负可表示有限数将满足向上舍入(向+∞)或向零舍入的比较。
等式对 double x = HUGE_VAL;
成立。从 C99 开始,引用 cppreference.com:
HUGE_VALF
、HUGE_VAL
和 HUGE_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;
}
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
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。