为什么这段倒写的代码打印出“Hello World!

2022-08-31 05:25:51

以下是我在互联网上找到的一些代码:

class M‮{public static void main(String[]a‭){System.out.print(new char[]
{'H','e','l','l','o',' ','W','o','r','l','d','!'});}}    

此代码打印到屏幕上;你可以看到它在这里运行。我可以清楚地看到书面的,但它是倒退的。此代码如何工作?这甚至如何编译?Hello World!public static void main

编辑:我在IntellIJ中尝试了这段代码,它工作正常。但是,由于某种原因,它与cmd一起在记事本++中不起作用。我仍然没有找到解决方案,所以如果有人这样做,请在下面发表评论。


答案 1

这里有一些不可见的字符,它们会改变代码的显示方式。在Intellij中,可以通过将代码复制粘贴到空字符串()中找到这些代码,该空字符串将它们替换为Unicode转义,删除它们的影响并揭示编译器看到的顺序。""

下面是该复制粘贴的输出:

"class M\u202E{public static void main(String[]a\u202D){System.out.print(new char[]\n"+
        "{'H','e','l','l','o',' ','W','o','r','l','d','!'});}}   "

源代码字符按此顺序存储,编译器将它们视为按此顺序存储,但它们的显示方式不同。

请注意,该字符是从右到左的覆盖,它启动一个块,其中所有字符都强制从右向左显示,而 ,这是从左到右的覆盖,它启动一个嵌套块,其中所有字符都强制按从左到右的顺序,覆盖第一个覆盖。\u202E\u202D

因此,当它显示原始代码时,正常显示,但是从那里反转所有内容的显示顺序,从而再次反转所有内容。(从形式上讲,从到行终止符的所有内容都会被反转两次,一次是由于 和 一次是由于 文本的其余部分由于 而反转,这就是为什么此文本显示在行的中间而不是末尾的原因。由于行终止符,下一行的方向性独立于第一行的方向性进行处理,因此正常显示。class M\u202E\u202D\u202D\u202D\u202E{'H','e','l','l','o',' ','W','o','r','l','d','!'});}}

有关完整的(极其复杂,数十页长)Unicode 双向算法,请参阅 Unicode 标准附录 #9


答案 2

由于Unicode双向算法,它看起来有所不同。有两个不可见的 RLO 和 LRO 字符,Unicode 双向算法使用它们来更改嵌套在这两个元字符之间的字符的可视外观

结果是,它们在视觉上看起来是相反的顺序,但内存中的实际字符并没有颠倒。您可以在此处分析结果。Java编译器将忽略RLO和LRO,并将它们视为空格,这就是代码编译的原因。

注1:文本编辑器和浏览器使用此算法同时直观地显示LTR字符(英语)和RTL字符(例如阿拉伯语,希伯来语)的字符 - 因此是“双向”方向的。您可以在Unicode的网站上阅读有关双向算法的更多信息。
注 2:LRO 和 RLO 的确切行为在算法的第 2.2 节中定义。


推荐