为什么1987年的Korn oneliner会打印Unix?

12

5
这个“问题”其实是一个谜题,而不是一个问题。 - Eric Postpischil
3
现在一个谜题可能会让人感到困惑,如果人们感到困惑,他们往往会问问题。 - glglgl
2个回答

14

unix的值为1,是由于编译器或运行环境中隐式定义了#define

因此,由于a[b] == b[a] == *(a + b),因此1["xy"] == "xy"[1],你会得到以下结果:

  • &unix["\021%six\012\0"]指向"%six\012\0"
  • (unix)["have"] = "have"[1] = 'a',
  • "'a'+"fun"-0x60" = "fun" + 1 = "un".

这将带你去printf("%six\012\0", "un");,显然会打印"unix\012",其中\012表示换行符(与\n相同)。

如果unix未定义,例如在Windows系统上,你会收到一个错误。

如果unix的值为0(在干净的系统上可能吗?),你会得到

printf("\012%six\n", 'h'+"fun"-0x60)

第二个参数是"fun"+8,指向涅槃,并导致未定义的行为。


4

通常情况下,我认为只有在类Unix系统下编译时才应该打印出“unix”。

这是因为在这样的系统中,“unix”是一个预定义宏,其值为1。

因此,它被翻译为:

main() { printf(&1["\021%six\012\0"], (1)["have"]+"fun"-0x60); }

重新排列以处理int [array]无用信息,我们得到:
main() { printf(&"\021%six\012\0"[1], "have"[1] + "fun"-0x60); }

我们可以忽略 \021,因为它被跳过了(我会用一个 ? 替换它),并将 \012 翻译成 \n

main() { printf(&"?%six\n\0"[1], 'a' + "fun" - 0x60); }
main() { printf(  "%six\n",     0x61 + "fun" - 0x60); }

这意味着:

main() { printf("%six\n", "un"); }

注意:我在解决问题时进行了重新整理(尤其是第二部分),但第一次看到它时,我需要两个提示才能理解解释:

  • unix 表示 1
  • int[array] 是编译器实际接受的符号。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接