好的,我会咬人的。广受欢迎的答案为什么 C 预处理器将单词“linux”解释为常量“1”?问题提到
main() { printf(&unix["\021%six\012\0"],(unix)["have"]+"fun"-0x60);}`
prints
"unix"
,但出于与宏名称的拼写完全无关的原因。
我阅读了http://www.ioccc.org/1987/korn.hint但我认为更多细节将有助于理解这一点:)
好的,我会咬人的。广受欢迎的答案为什么 C 预处理器将单词“linux”解释为常量“1”?问题提到
main() { printf(&unix["\021%six\012\0"],(unix)["have"]+"fun"-0x60);}`
prints
"unix"
,但出于与宏名称的拼写完全无关的原因。
我阅读了http://www.ioccc.org/1987/korn.hint但我认为更多细节将有助于理解这一点:)
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 系统上,则会出现错误。
如果unix
是0
(这可能是干净系统上的方式吗?),你会得到
printf("\012%six\n", 'h'+"fun"-0x60)
其中第二个参数是"fun"+8
,指向 Nirvana 并导致未定义的行为。
通常我认为只有在类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]
是编译器接受的实际符号。