Visual C++ と gcc 共有ソースでの文字コードについて


UTF-8N のソースを VC++ でコンパイルするとエラー

最近、Qt を使って Linux/Windows の両方で動作するアプリケーションを作成しています。Linux では gcc、Windows では Visual C++ 2010 Express を使ってコンパイルしています。今回、Linux 上でアプリケーションを開発し、動作テストも終えたところで Windows でコンパイルしたところ、以下の様なエラーが発生しました。

warning C4819: The file contains a character that cannot be represented in the current code page (932). Save the file in Unicode format to prevent data loss
.
.
error C2614: ‘***’ : illegal member initialization: ‘***’ is not a base or member
.
.
error C2065: ‘***’ : undeclared identifier

最初、後半の error 部分 (C2614, C0265) を見てクラス宣言が不完全なのかと思い、ソースを確認してみましたが特におかしな所は見受けられません。

となると、その上の warning C4819 が引っかかります。今回のソースは UTF-8 ですが、メッセージを見る限り CP932 と認識している様子です。UTF-8 と言っても日本語処理を行なっているわけではなく、ただコメントが日本語で書いてあるだけです。しかし、念のためコメント部分を削除してコンパイルすると問題なくコンパイルできました。

最初はコメントだけなら日本語があってもそれ程問題にならないだろうと思っていましたが、そういうわけにもいかないようです。簡単なテストコードも書いてみましたが、警告だけでエラーにはならない場合もありました。そんなわけで、Linux (gcc) / Windows (Visual C++) の両方でコンパイルするためには、ソースをどんなエンコードで保存すれば良いのか調べてみました。

Visual C++ と gcc で共通ソースを使うには

Visual C++ で日本語を扱う時の基本は、CP932 (SJIS) のようです。しかし、UNICODE を扱うことも可能です。コンパイラおよびリンカーでの Unicode のサポート によれば、UTF-8 では BOM 付きのみサポートされているようです。

一方、gcc では CP932(SJIS) は対応していません。UTF-8 は、以前は BOM 無しの UTF-8 のみがサポートされていたようです。しかし、Bug 33415 – Can’t compile .cpp file with UTF-8 BOM. によれば、2008 年頃には BOM 付き UTF-8 に対応されるようになりました。バージョンで言うと 4.3.x 以降ということのようです。

以上のことから、BOM 付き UTF-8 であれば、Visual C++ と gcc で共通のソースコードを利用できることがわかりました。

UTF-8 の BOM について

BOM (Byte Order Mark) は、本来 UTF-16 においてアーキテクチャによるエンディアン(バイトの並び順)の違いを先頭の数バイトで判断するために設けられたもので、UTF-8 では不要なはずです。ただ、これがあると UTF-8 であるかどうか判定がしやすいため、Microsoft では BOM 付き UTF-8 を採用しているのだと思います。

通常は、UTF-8 とだけ言う場合は BOM 無しを指すことが多いと思いますが、BOM 付きの UTF-8 と区別するために BOM 無しの UTF-8 のことを、UTF-8N と記述することもあります。その場合、UTF-8 は BOM 付きを意味します。(ややこしい)

BOM 付きの UTF-8 では、先頭 3 バイトが 0xEF, 0xBB, 0xBF になります。Windows でファイルの BOM を確認するには、エディタの判別機能を使うか、Stirling (Vector で検索してください) 等のバイナリエディタを使ってください。

Linux では、file コマンドを使って簡単に調べられます。

Qt Creator 2.7.0 で BOM 付き UTF-8 を使うには

メニューの Tools > Options… で、Behavior タブを開き、File Encodings の項目で、

Default encoding: UTF-8
UTF-8 BOM: Add if Encoding Is UTF-8

を設定します。

ただし、BOM 無し UTF-8 で保存された既存のファイルは、明示的に上書き保存 (Save as …) しないと BOM 付きに変更されません。

[参考にしたサイト]

メールアドレスが公開されることはありません。