Почему этот код, написанный задом наперед, печатает " Hello World!"



вот какой код я нашел в Интернете:



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 написано, но все наоборот. Как работает этот код? Как это вообще компилируется?



Edit: Я пробовал этот код в IntellIJ, и он отлично работает. Однако по какой-то причине он не работает в notepad++ вместе с cmd. Я до сих пор не нашел решение, так что если кто делает, комментарий ниже.

705   4  

4 ответов:

здесь есть невидимые символы, которые изменяют способ отображения кода. В Intellij их можно найти путем копирования-вставки кода в пустую строку (""), который заменяет их экранированием Unicode, удаляя их эффекты и раскрывая порядок, который видит компилятор.

вот результат этой copy-paste:

"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, который является переопределением слева направо, начиная вложенный блок, где все символы принудительно расположены в порядке слева направо, переопределяя первое переопределение.

Ergo, когда он отображает исходный код,class M отображается нормально, но \u202E изменяет порядок отображения всего из там к \u202D, который снова все переворачивает. (Формально, все от \u202D к линии Терминатор получает обратный дважды, один раз из-за \u202D и один раз с остальной частью текста перевернуто из-за \u202E, именно поэтому этот текст отображается в середине строки вместо конца.) Направленность следующей строки обрабатывается независимо от первой из-за Терминатора строки, поэтому {'H','e','l','l','o',' ','W','o','r','l','d','!'});}} отображается нормально.

для полного (чрезвычайно сложного, десятки страниц длиной) двунаправленный алгоритм Юникода, см. Unicode Standard Annex #9.

Это выглядит по-другому из-за Unicode Двунаправленный Алгоритм. Существует два невидимых символа RLO и LRO, которые двунаправленный алгоритм Unicode использует для изменения внешний вид символов, вложенных между этими двумя метасимволами.

в результате визуально они смотрят в обратном порядке, но фактические символы в не восстанавливаются. Вы можете проанализировать результаты здесь. Компилятор Java будет игнорировать RLO и LRO и рассматривать их как пробелы, поэтому код компилируется.

Примечание 1: Этот алгоритм используется текстовыми редакторами и браузерами для визуального отображения символов как LTR символов (английский), так и RTL символов (например Арабский, иврит) вместе в то же время-отсюда и "Би" - направленный. Вы можете узнать больше о Двунаправленном алгоритме в Юникоде сайт.
примечание 2: Точное поведение LRO и RLO определяется в 2.2 of алгоритм.

Символ U+202E отражает код справа налево, это очень умный, хотя. Скрыто начиная с M,

"class M\u202E{..."

как я нашел магия за это?

Ну, сначала, когда я увидел вопрос, я жесткий, "это своего рода шутка, чтобы потерять чье-то время", но затем я открыл свою IDE ("IntelliJ"), создал класс и прошел код... и он составлен!!! Итак, я посмотрел получше и увидел, что "публичная статическая пустота" была обратной, поэтому я пошел туда с курсором,и стереть несколько символов... И что же происходит? символы начали стирать назад Итак, я подумал МММ.... редкий... Я должен его исполнить... Поэтому я приступаю к выполнению программы, но сначала мне нужно сохранить... и это было когда я нашел его!. Я не мог сохранить файл, потому что моя IDE сказала, что для некоторых символов существует другая кодировка,и мне где это было, поэтому я начинаю исследование в Google для специальных символов, которые могли бы выполнить эту работу, и это все:)

о

двунаправленный алгоритм Юникода, и U+202E участвует, кратко объяснить:

стандарт Unicode предписывает порядок представления памяти, известный как логический порядок. Когда текст представлен горизонтальными линиями, большинство скриптов отображают символы слева направо. Однако, существует несколько сценариев (например, арабский или иврит), где естественный порядок горизонтального текста отображается справа налево. Если весь текст имеет равномерное горизонтальное направление, то порядок отображения текста однозначен.

однако, поскольку эти сценарии справа налево используют цифры, написанные слева направо, текст на самом деле двунаправленный: смесь текста справа налево и слева направо. В дополнение к цифрам, встроенным словам с английского и другие сценарии также пишутся слева направо, также создавая двунаправленный текст. Без четкой спецификации могут возникнуть неясности в определении порядка отображаемых символов, когда горизонтальное направление текста не является однородным.

В этом приложении описывается алгоритм, используемый для определения направленности двунаправленного текста Юникода. Алгоритм расширяет неявную модель, используемую в настоящее время рядом существующих реализаций, и добавляет явную форматирование символов для особых обстоятельств. В большинстве случаев нет необходимости включать дополнительную информацию с текстом для получения правильного порядка отображения.

однако в случае двунаправленного текста существуют обстоятельства, при которых неявного двунаправленного упорядочения недостаточно для получения понятного текста. Чтобы справиться с этими случаями, определяется минимальный набор символов направленного форматирования для управления порядком символов при визуализации. Это позволяет точный контроль порядка отображения для разборчивого обмена и гарантирует, что простой текст, используемый для простых элементов, таких как имена файлов или метки, всегда может быть правильно упорядочен для отображения.

зачем создавать какой-то алгоритм, как этой?

алгоритм bidi может отображать последовательность арабского или иврита персонажи один за другим справа налево.

P. S.: Я знаю, что это не лучший ответ, но это было весело, чтобы взломать проблема первая: P

Глава 3 спецификации языка дает объяснение, подробно описывая, как лексический перевод выполняется для программы Java. Что наиболее важно для вопроса:

программы написаны в Юникоде (§3.1), но лексические переводы предоставляются (§3.2), так что Unicode escapes (§3.3) можно использовать для включения любого символа Unicode, используя только символы ASCII.

таким образом, программа написана в Символы Юникода, и автор может избежать их с помощью \uxxxx в случае, если кодировка файла не поддерживает Юникод, в этом случае он переводится на соответствующий символ. Один из символов Юникода, присутствующих в этом случае, -\u202E. Он визуально не отображается в сниппете, но если вы попытаетесь переключить кодировку браузера, могут появиться скрытые символы.

таким образом, лексический перевод приводит к классу объявление:

class M\u202E{

это означает, что идентификатор класса M\u202E. Элемент спецификация считает это допустимым идентификатором:

Identifier:
    IdentifierChars but not a Keyword or BooleanLiteral or NullLiteral
IdentifierChars:
    JavaLetter {JavaLetterOrDigit}

"Java letter-or-digit" - это символ, для которого метод Character.isJavaIdentifierPart(int) возвращает true.

Comments

    Ничего не найдено.