この記事では、
Bad configuration option: \377\376h
が表示されたときに何が起こっているか、そしてどうすれば直るかを説明します。
原理はいいから解説を見たい!という人は「解決策」までスクロールしてください。
#前提知識その1 Unicode
Unicodeとは、簡単に言うと「コンピュータで文字を管理しやすくするために、世界中(※一部地域を除く)の文字に0番から65535番までの番号を付けた規格」です。
「A」はU+0041、「麻」はU+9EBB、・・・のように、「U+」の後に番号を表す4桁の16進数を付けて表現することが一般的です。
文字列を扱うときは、これらの文字の番号を並べて表します。例えば青い鳥
という文字列の文字の番号を並べると
9752 3044 9CE5
となりますが、青い鳥
と書かれたtxtをバイナリエディタで開いてもこれがそのまま見えるわけではありません。
#前提知識その2 エンディアン
コンピュータで2バイト以上の数を扱うときは、2種類の保存方法があります。ビッグエンディアンとリトルエンディアンです。
##ビッグエンディアン
バイトを「左から順」に並べる方法です。例えば0x01020304(十進数の16,909,060)は
01 02 03 04
という順序で保存されます。ビッグエンディアンは、人間が書くのと同じようにメモリに保存されるので、人間にとってわかりやすいというメリットがあります。
##リトルエンディアン
バイトを「右から順」に並べる方法です。例えば0x01020304(十進数の16,909,060)は
04 03 02 01
という順序で保存されます。リトルエンディアンは、コンピュータの内部で処理するのに都合がいいというメリットがあります。
#前提知識その3 BOM
では、保存されたデータがビッグエンディアンなのかリトルエンディアンなのかを判断するには、どうすればよいでしょうか? そのために、Unicodeには特殊な文字が用意されています。それが、Byte Order Mark、通称BOMと呼ばれる、U+FEFF(65279番)の文字です。この文字は見た目上は何もありませんが、コンピュータ上でビッグエンディアンとリトルエンディアンを区別するために使われます。
実際には、テキストの最初にこの文字を最初に置くことで、FE FF
であればビッグエンディアン、FF FE
であればリトルエンディアンとして区別できます。
しかし、必ずしもBOMがテキストの最初にあるとは限らないので、「最初の文字がたまたまU+FFFEだったら逆に認識されるのではないか?」という疑問が生まれます。そこはすでに対策済で、「U+FFFEは「文字ではない」とする」ことで解決しています。つまり、意図的にそうしない限りU+FFFEがテキストに現れることはないので、U+FFFEを見たらU+FFEFを間違ったエンディアンで読んだものだとわかる、というわけです。
#前提知識その4 \+3桁
CやRubyなどのプログラミング言語では、バックスラッシュ(\
、フォントによっては円記号として表示される)の後に0~7の数字を1個~3個続けることで、「八進数でその値をUnicodeの番号として持つ文字」を表すことができます(ただし、八進数の400
以上の数を指定した場合に実際にどうなるかは言語や環境に依存します)。
たとえば、\63
と書くと八進数の63、つまり51番の文字(数字の3)になり、\123
と書くと八進数の123、つまり83番の文字(大文字のS)になります。
#前提知識その5 UTF-8
UTF-8というエンコーディング方式があります。これもUnicodeを基にしているのですが、少し特殊で「0番から127番までは番号を1バイトでそのまま表せる」という性質があります。
#以上の知識をまとめると・・・?
では、\377\376h
について考えていきましょう。八進数の377
は十六進数でFF
、八進数の376
は十六進数でFE
です。そのままつなげるとFF FE
ですが、これはエンディアンを間違えたBOMですね。逆順に並べるとFE FF
となり、この2文字がBOMであることがわかります。逆順なので、リトルエンディアンですね。
h
はおそらく本来のテキストの最初の文字です。ということは、BOMを外してあげればコンピュータに認識できそうですね。
#解決策
UTF-8に置き換えれば解決します。UTF-8に変換する場合、自動的にBOMが外れることが多く(少なくとも私の使っているエディタはそうでした)、元のテキストがASCII文字であればUTF-8でもASCIIでも同じバイト列になるため、コンピュータも「なんだこの文字は!?」というエラーを出すことがなくなります(今度は内容に対するエラーが出るかもしれませんが)。