Programing

거꾸로 작성된이 코드가“Hello World!”를 인쇄하는 이유는 무엇입니까?

lottogame 2020. 4. 4. 10:12
반응형

거꾸로 작성된이 코드가“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글을 볼 수 있지만, 거꾸로입니다. 이 코드는 어떻게 작동합니까? 어떻게 컴파일합니까?

편집 : IntellIJ 에서이 코드를 시도했지만 정상적으로 작동합니다. 그러나 어떤 이유로 든 cmd와 함께 notepad ++에서는 작동하지 않습니다. 나는 여전히 그것에 대한 해결책을 찾지 못했습니다. 그렇다면 누군가 아래에 의견을 적으십시오.


코드 표시 방법을 변경하는 보이지 않는 문자가 여기에 있습니다. Intellij에서는 코드를 빈 문자열 ( "") 에 복사하여 붙여 넣을 수 있습니다.이 문자열 은 유니 코드 이스케이프로 대체되어 영향을 제거하고 컴파일러가 보는 순서를 나타냅니다.

해당 복사 붙여 넣기의 출력은 다음과 같습니다.

"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','!'});}}정상적으로 표시됩니다.

전체 (매우 복잡한 수십 페이지 길이) 유니 코드 양방향 알고리즘에 대해서는 유니 코드 표준 부록 # 9를 참조하십시오 .


Unicode Bidirectional Algorithm 때문에 다르게 보입니다 . 유니 코드 양방향 알고리즘 이이 두 메타 문자 사이에 중첩 된 문자 시각적 모양 을 변경하는 데 사용하는 두 가지 보이지 않는 RLO 및 LRO 문자가 있습니다.

결과적 으로 시각적으로 역순 으로 보이지만 메모리 의 실제 문자 반전되지 않습니다. 여기 에서 결과를 분석 할 수 있습니다 . Java 컴파일러는 RLO 및 LRO를 무시하고 공백으로 처리하므로 코드가 컴파일됩니다.

참고 1 :이 알고리즘은 텍스트 편집기와 브라우저에서 LTR 문자 (영어)와 RTL 문자 (예 : 아랍어, 히브리어)를 동시에 시각적으로 표시하기 위해 사용되므로 "bi"방향입니다. 양방향 알고리즘에 대한 자세한 내용은 유니 코드 웹 사이트를 참조하십시오 .
참고 2 : LRO 및 RLO의 정확한 동작은 알고리즘 2.2정의되어 있습니다.


캐릭터 U+202E는 코드를 오른쪽에서 왼쪽으로 미러링하지만 매우 영리합니다. M부터 시작해서 숨겨져 있고

"class M\u202E{..."

이 뒤에 숨겨진 마법을 어떻게 찾았 습니까?

글쎄, 처음에 내가 힘든 질문을 보았을 때, "다른 사람을 잃는 것은 일종의 농담입니다."하지만 IDE ( "IntelliJ")를 열고 클래스를 만들고 코드를 지나서 ... 그리고 그것은 컴파일되었습니다 !!! 그래서 나는 더 나은 모습을 보았고 "공공 정적 공백"이 뒤로 있다는 것을 알았으므로 커서로 거기에 가서 몇 개의 문자를 삭제했습니다 ... 그리고 어떻게됩니까? 문자가 뒤로 지우기 시작 했으므로 mmm .... rare ... 나는 그것을 실행해야한다고 생각했습니다. 그래서 프로그램을 실행해야하지만 먼저 저장해야했습니다 ... 그리고 그 때였습니다. 그것을 발견! . IDE에서 일부 문자에 대해 다른 인코딩이 있다고 말하고 파일이 어디에 있는지 알려 주기 때문에 파일을 저장할 수 없습니다., 그래서 나는 일을 할 수있는 특별한 숯에 대해 Google에서 연구를 시작합니다.

조금

Unicode Bidirectional Algorithm과 U+202E관련된 간단한 설명 :

유니 코드 표준은 논리적 순서로 알려진 메모리 표현 순서를 규정합니다. 텍스트가 수평선으로 표시되면 대부분의 스크립트는 왼쪽에서 오른쪽으로 문자를 표시합니다. 그러나 표시되는 가로 텍스트의 자연 순서가 오른쪽에서 왼쪽 인 여러 스크립트 (예 : 아랍어 또는 히브리어)가 있습니다. 모든 텍스트의 가로 방향이 균일하면 표시 텍스트의 순서가 명확합니다.

그러나 이러한 오른쪽에서 왼쪽으로 쓰는 스크립트는 왼쪽에서 오른쪽으로 쓴 숫자를 사용하기 때문에 텍스트는 실제로 양방향입니다. 오른쪽에서 왼쪽 및 왼쪽에서 오른쪽으로 텍스트가 혼합되어 있습니다. 숫자 외에도 영어 및 기타 스크립트의 내장 단어가 왼쪽에서 오른쪽으로 작성되어 양방향 텍스트도 생성합니다. 명확한 지정이 없으면 텍스트의 가로 방향이 균일하지 않은 경우 표시되는 문자의 순서를 결정하는 데 모호성이 발생할 수 있습니다.

이 부록은 양방향 유니 코드 텍스트의 방향성을 결정하는 데 사용되는 알고리즘을 설명합니다. 이 알고리즘은 여러 기존 구현에서 현재 사용하는 암시 적 모델을 확장하고 특수한 상황을 위해 명시 적 서식 문자를 추가합니다. 대부분의 경우 올바른 표시 순서를 얻기 위해 텍스트에 추가 정보를 포함 할 필요가 없습니다.

그러나 양방향 텍스트의 경우 암시적인 양방향 순서가 이해하기 어려운 텍스트를 생성하기에 충분하지 않은 상황이 있습니다. 이러한 경우를 처리하기 위해 렌더링시 문자 순서를 제어하기 위해 최소 방향 서식 문자 세트가 정의됩니다. 이를 통해 읽기 쉬운 교환을위한 디스플레이 순서를 정확하게 제어 할 수 있으며 파일 이름이나 레이블과 같은 간단한 항목에 사용되는 일반 텍스트를 항상 올바르게 표시 할 수 있습니다.

이런 알고리즘을 만들 까요?

bidi 알고리즘은 오른쪽에서 왼쪽으로 차례로 일련의 아랍어 또는 히브리어 문자를 렌더링 할 수 있습니다.

추신 : 나는 그것이 최선의 대답은 아니라는 것을 알고 있지만 문제를 먼저 해결하는 것은 재미있었습니다. : P


언어 사양의 3 장 에서는 Java 프로그램에서 어휘 변환이 수행되는 방법을 자세히 설명하여 설명합니다. 질문에서 가장 중요한 것은 :

프로그램은 유니 코드 (§3.1)로 작성 되지만, 어휘 변환 (§3.2)이 제공되므로 유니 코드 이스케이프 (§3.3)를 사용하여 ASCII 문자 만 사용하는 유니 코드 문자를 포함 할 수 있습니다.

따라서 프로그램은 유니 코드 문자로 작성되며 \uxxxx파일 인코딩이 유니 코드 문자를 지원하지 않는 경우 이를 사용하여 프로그램 이스케이프 처리 할 수 ​​있습니다 .이 경우 적절한 문자로 변환됩니다. 이 경우 존재하는 유니 코드 문자 중 하나는 \u202E입니다. 스 니펫에는 시각적으로 표시되지 않지만 브라우저의 인코딩을 전환하려고하면 숨겨진 문자가 나타날 수 있습니다.

따라서 어휘 변환으로 클래스 선언이 발생합니다.

class M\u202E{

이는 클래스 식별자가임을 의미합니다 M\u202E. 사양은 유효한 식별자로 이것을 고려 :

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

"자바 문자"는 메소드 Character.isJavaIdentifierPart(int)가 true를 리턴 하는 문자입니다 .

참고 URL : https://stackoverflow.com/questions/43943699/why-does-this-code-written-backwards-print-hello-world

반응형