关于C#:为什么1987 Korn oneliner打印unix?

Why does the 1987 Korn oneliner print unix?

好的,我会咬人的。 大众流行的答案为什么C预处理器将单词"linux"解释为常量"1"? 问题提到

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

prints "unix", but for reasons that have absolutely nothing to do with the spelling of the macro name.

我阅读http://www.ioccc.org/1987/korn.hint,但我认为更多的细节将有助于不混淆这:)


由于编译器或运行时环境中存在隐式#define,因此unix为1。

因此,因为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是换行符(与
相同)。

如果unix未定义,e。 G。在Windows系统上,您收到错误。

如果unix 0(这可能是一个干净的系统吗?),你得到

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

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


通常我认为它应该只在unix类系统下编译时打印"unix"。

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

因此,它翻译为:

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

重新命令处置int[array]废话,我们得到:

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

我们可以忽略\021,因为它被跳过(我只是用?替换它),并将\012转换为

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

这使:

1
2
main() { printf("%six
"
,"un"); }

注意:我一直在重新解决它(特别是第二部分),但是第一次看到它时我需要两个提示才能理解解释:

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