文字コードの違いはアプリケーションが吸収する


概要

先日、文字コードについて考えているとき、ふと以下のような疑問を持ちました。

「バイト列は文字コードによって異なるはずなのに、コンピュータはどうやってそれを認識しているのだろう?」

私自身実力不足で、この疑問を持ちましたが、今回は勉強したことをまとめてみました。

結論

結論としては、我々が入力するプログラムの文字コードの違いは、コンパイラ等のアプリケーションによって一意のバイト列に変換されるため、プログラムの文字コードはCPU等のハードウェアに影響を与えないということが言えます。

本来の私の想定

実際の動き


しかし、よく考えたらもしアプリケーションが「本来の私の想定」の動きをしているなら、コンパイラはなにをしているんだという話になります。 改めて私の勉強不足を痛感させられました。

実験してみた

⓪ 仮説

① あるJavaファイルを別々の場所に計2回保存する。保存の際、それぞれは別の文字コードで保存する。(同じソースだが、違う文字コードで保存されたものができる)
② ①で作成したファイルの差分をバイナリデータで比較すると、別々の文字コードで保存しているため、差分が確認されるはず
③ それぞれをclassファイルに変換する
④ それぞれのclassファイルの差分を比較すると、差分は確認されないはず

① 別々の文字コードで保存した、同じソースを用意する

HelloWorld.javaを参考に、以下のソースを用意します。

HelloWorld.java
public class HelloWorld {

    public static void main(String[] args) {
        // Prints "Hello, World" to the terminal window.
        System.out.println("Hello, World");
    }

}

保存したらそれぞれのファイルの文字コードを確認します。


ソースは同じですが、文字コードが違っていることがわかります。

② ①の差分をとる


バイナリデータに差分があることがわかります。

③ それぞれをclassファイルにコンパイルする

UTF-16のほうをコンパイル
javac -encoding UTF-16 HelloWorld.java
UTF-8のほうをコンパイル
javac HelloWorld.java

④ classファイルの差分をとる


差分がない!

結果

ソースの文字コードの違いはコンパイラによって吸収され、一意のバイト列に変換されていることがわかりました。

上記の実験はJavaで行いましたが、実際はこの後classファイルがJVMによってマシン語に変換され、CPUがそれをプログラムとして実行するようです。ですので、今回の実験では我々の入力するインプットの文字コードの違いはclassファイルにコンパイルされる段階でまとめられてしまうことがわかりました。

参考:
今さらだけど・・・Javaは2回「コンパイル」されているのを知らなかった!(><)

まとめ

本来「文字コードによってバイト列は異なるはずなのに、ハードウェアはそれをどう認識しているのだろう」という疑問をもったことから、上記で書いたことを調べてみました。しかし、この疑問もコンパイラの役割をきちんと理解できていなかったからこそ湧いた疑問なのかもしれません。 あらためてアプリケーションの基本的な事項を勉強しておくことの大切さを実感しました。