そのままコンパイルすると、
foo.c:6:21: warning: unknown escape sequence: '\201'というエラーになってしまいます。
これは「ソー」をShitfJISでエンコードすると、0x83、0x5c、0x81、0x5bになることが原因です。0x5c(バックスラッシュ)の次の文字として、Cで定義されたエスケープシーケンスを構成する文字(例えば'\'+'n'で「改行」等)を期待しているのに、未知の文字(ここでは、0x81)が来たよ、というエラーです。
ある意味ここまでは想定の範囲内。iconv サポートを有効にして生成された gcc の場合、入力ファイルの文字コードを指定できますから、次のように「このファイルは SJIS ですよ」と指定して、コンパイルしてみました。
% gcc -finput-charset=SJIS -O2 -Wall foo.cすると今度は、今まで問題なく通っていた'\'がことごとくエラーになってしまいました。慌てて変換結果を良く見ると、なるほど、'\'はすべて0xa5に展開されていました。
実は、これは iconv の採用している ShiftJIS <-> UTF-8 変換テーブルが、Unicode 1.1 で定義された変換テーブルに基づいている為です。JIS X 0201の0x5cは「YEN SIGN」ですから、これは意味論上、全く正しい変換なのですが、今回の例では、少し困ってしまいます。
幸い、Shift-JIS の Windows 版実装とでも言える「Windows-31J」に基づく「CP932」では、UTF-8の変換テーブルでは、'\'は0x5cへと展開するように定義されています。今回は、該当ファイルがWindows上で作られたこともありますので、それを用いることにしましょう。
% gcc -finput-charset=CP932 -O2 -Wall foo.c今度は問題なくコンパイルできました。
日頃からShiftJISとUnicodeの変換テーブルの揺れが引き起こす問題には気を使っているのですが、まさかコンパイル時に出くわすとは思っていなかったので、新鮮な驚きでした。
というわけで結論。
- 日本語文字列をコード中に埋め込むのは避けよう。
- どうしても、ShiftJISでエンコードされた文字列の埋め込まれたコードをコンパイルする場合には、そのファイルがWindows上で生成された場合には、入力ファイルの文字コードにCP932を指定しよう。
0 件のコメント:
コメントを投稿