11

好的,我会咬人的。广受欢迎的答案为什么 C 预处理器将单词“linux”解释为常量“1”?问题提到

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

prints "unix",但出于与宏名称的拼写完全无关的原因。

我阅读了http://www.ioccc.org/1987/korn.hint但我认为更多细节将有助于理解这一点:)

4

2 回答 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");清楚地知道 print"unix\012"\012一个换行符(与 相同\n)。

如果unix未定义,例如在 Windows 系统上,则会出现错误。

如果unix0(这可能是干净系统上的方式吗?),你会得到

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

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

于 2013-10-10T14:42:11.047 回答
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因为它被跳过了(我将用 a 替换它?),并将其翻译\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]是编译器接受的实际符号。
于 2013-10-10T14:40:26.957 回答