これはJavaでポインタで使えるというネタから着想を得たプログラミングネタです。
厳密には 「コメントだけ書いてあるようにしか見えない」 です。
コメントだけしか書いていないのに「Hello, world!」と表示されるJavaプログラム
% java --version
openjdk 16.0.2 2021-07-20
OpenJDK Runtime Environment Microsoft-25298 (build 16.0.2+7)
OpenJDK 64-Bit Server VM Microsoft-25298 (build 16.0.2+7, mixed mode)
「百聞は一見にしかず」なので、まずは見てみましょう。
import java.util.*;
public class Main {
public static void main(String[] args) throws Exception {
//\u000a\u0053\u0079\u0073\u0074\u0065\u006d\u002e\u006f\u0075\u0074\u002e\u0070\u0072\u0069\u006e\u0074\u006c\u006e\u0028\u0022\u0048\u0065\u006c\u006c\u006f\u002c\u0020\u0077\u006f\u0072\u006c\u0064\u0021\u0022\u0029\u003b
}
}
シンタックスハイライトだと、main関数の中にはコメントしかないですね。
しかし、実行すると「Hello, world!」と出力されます。
% java Main.java
Hello, world!
種明かし
Javaはコンパイル前に、 ソースコード中のUnicodeエスケープシーケンスをテキストへ変換する。
\u000a
は改行なので、 //\u000a
で実はコメントが終わっている。
そのため、それより後に書かれたテキストは、プログラムとしてコンパイルされる。
\u0053\u0079...
のように、Unicodeエスケープシーケンスでプログラムを書いておけば、コメントの中にプログラムを仕込むことができる。
Unicodeエスケープシーケンスを展開すると、System.out.println("Hello, world!");
となる。
コンパイラが認識している文字列は以下のようになっている。
import java.util.*;
public class Main {
public static void main(String[] args) throws Exception {
//
System.out.println("Hello, world!");
}
}
シンタックスハイライトにハイライトに騙されるところでしたね。
Javaでポインタが使える
着想の元になった記事の内容です。コードと種明かしだけ掲載しておきます。
*演算子を用いてJavaでポインタを扱う
public class PointerTest {
public static void main(String[] args) {
int i = 5;
// #start unsafe# http://java.sun.com\u000a\u002f\u002a
int *ip = &i;
// ポインタの内容に3を加算
*ip += 3;
// 演算結果をiに代入
i = *ip;
// #end unsafe# http://java.sun.com\u002a\u002fi+=\u0033\u003b
System.out.println(i);
}
}
種明かし
public class PointerTest {
public static void main(String[] args) {
int i = 5;
// #start unsafe# http://java.sun.com
/*
int *ip = &i;
// ポインタの内容に3を加算
*ip += 3;
// 演算結果をiに代入
i = *ip;
// #end unsafe# http://java.sun.com*/i+=3;
System.out.println(i);
}
}
本当にコメントだけしか書いていないのに「Hello, world!」と表示されるJavaプログラム
ソースコードに記述されてるすべてのUnicodeエスケープシーケンスが展開されるのなら、
プログラムすべてを、Unicodeエスケープシーケンスで記述しても動作するのではないか?
そこで作ってみた。
//\u000a\u0069\u006d\u0070\u006f\u0072\u0074\u0020\u006a\u0061\u0076\u0061\u002e\u0075\u0074\u0069\u006c\u002e\u002a\u003b\u000a\u000a\u0070\u0075\u0062\u006c\u0069\u0063\u0020\u0063\u006c\u0061\u0073\u0073\u0020\u004d\u0061\u0069\u006e\u0032\u0020\u007b\u000a\u0020\u0020\u0020\u0020\u0070\u0075\u0062\u006c\u0069\u0063\u0020\u0073\u0074\u0061\u0074\u0069\u0063\u0020\u0076\u006f\u0069\u0064\u0020\u006d\u0061\u0069\u006e\u0028\u0053\u0074\u0072\u0069\u006e\u0067\u005b\u005d\u0020\u0061\u0072\u0067\u0073\u0029\u0020\u0074\u0068\u0072\u006f\u0077\u0073\u0020\u0045\u0078\u0063\u0065\u0070\u0074\u0069\u006f\u006e\u0020\u007b\u000a\u0020\u0020\u0020\u0020\u0020\u0020\u0020\u0020\u0053\u0079\u0073\u0074\u0065\u006d\u002e\u006f\u0075\u0074\u002e\u0070\u0072\u0069\u006e\u0074\u006c\u006e\u0028\u0022\u0048\u0065\u006c\u006c\u006f\u002c\u0020\u0077\u006f\u0072\u006c\u0064\u0021\u0022\u0029\u003b\u000a\u0020\u0020\u0020\u0020\u007d\u000a\u007d\u000a
% java Main2.java
Hello, world!
本当に コメントだけしかないように見える プログラムもしっかり動作した。
その他
-
Javaの言語仕様はここから読める。
https://docs.oracle.com/javase/specs/index.html -
Unicode関する記述はここ。
https://docs.oracle.com/javase/specs/jls/se16/html/jls-3.html -
コンパイラの実装はここから読めるのでコードリーディングして辿っていきたい。
最後に
ラインコメント(一行のコメント)に\u000a
と記述したら大変なことになりそうです。