Visual Studio / C++ における「文字コード・文字型・プレフィックス」の関係まとめ

記事

 今回の記事は自分が右往左往したVisualStudio/C++環境下においての文字コード・文字型・プレフィックスの関係性について、ChatGPTにまとめてもらったものです。

文字関係の問題に悩む人の一助になればと思います。どうぞ。

少しお願いしたいのですが、VisualStudioおよびC++における文字コード・型の関係をブログで公開できるような形式でまとめてもらえませんか。
具体的には
1.Unicode文字・マルチバイト文字の説明(それぞれ簡潔に1~3行程度?)
2. C++における文字型の解説(型ごとにそれぞれ1~5行程度?)
3. 文字プレフィックスの説明
4. 相互にどのような関係があるのか
5. どういったプロジェクト・条件で使い分ければいいのか

この記事では、Visual Studio の「Unicode / マルチバイト文字セット」と、C++ の文字型・文字列リテラル(プレフィックス)・エンコーディングが、どう噛み合っているのかを整理します。


1. 「Unicode文字」と「マルチバイト文字」の説明(Visual Studio の設定)

Unicode文字セット

Windows API を含む多くの現代的な Windows 開発で標準的な設定です。内部的には「ワイド文字(wchar_t)」を使う流儀になり、Win32 API も基本的に ...W(Wide)側を使うことになります。

マルチバイト文字セット

いわゆる「ANSI(A)」系APIや、Shift-JIS/CP932 前提の資産に寄せた設定です。TCHARchar 側に寄り、文字列が OS のコードページ(日本語Windowsなら CP932)依存になりやすくなります。


2. C++ における文字型の解説(型ごと)

char

1バイトの文字型です。std::string の要素型でもあり、実務では「文字」よりも「バイト列の器」として使われることが多いです。中身が UTF-8 なのか Shift-JIS なのかは運用ルール次第です。

signed char / unsigned char

同じく1バイトですが、符号付き/符号なしが明確です。バイナリ処理やバイト配列として扱いたいときに便利で、文字コード用途というより「生のデータ」用途で登場します。

wchar_t

ワイド文字型です。Windows では多くの場合 16bit(UTF-16 のコードユニットとして運用されがち)で、Win32 API(W系)との相性が良いです。ただし規格上「必ずUTF-16」という保証ではありません。

char16_t

16bit固定の文字型で、UTF-16 のコードユニット列を表現するための型です。プラットフォーム差が少なく、UTF-16 を明示したいときに使います。

char32_t

32bit固定の文字型で、UTF-32 を表現するための型です。コードポイント単位の処理がしやすい反面、サイズは大きめです。

char8_t(C++20)

UTF-8 用の文字型です。u8"..." リテラルの型が char8_t[] になり、std::u8string との親和性が高いです。一方で std::stringchar)と混ぜると型変換が必要になることがあります。


3. 文字列リテラルのプレフィックス(例つき)

C++ の「プレフィックス」は、主に“リテラルの型”を変えます(Shift-JISなど特定コードページを直接指定する機能ではありません)。

  • "text"const char[]
  • L"text"const wchar_t[]
  • u8"text"const char8_t[](C++20以降)
  • u"text"const char16_t[]
  • U"text"const char32_t[]

また、Raw文字列(エスケープを気にしない)も組み合わせ可能です:

  • R"(C:\path\file.txt)"
  • u8R"(改行\nもそのまま)"

4. それぞれがどう関係しているか(混乱ポイントの整理)

ここが一番大事です。

4-1. 「Visual Studioの文字セット」は何を変える?

Visual Studio の「Unicode / マルチバイト文字セット」は、主に Windows API 呼び出しや TCHARの挙動に影響します。

  • Unicode文字セット:TCHARwchar_tMessageBoxMessageBoxW のように Wide 側へ寄る
  • マルチバイト文字セット:TCHARcharMessageBoxMessageBoxA のように ANSI 側へ寄る

4-2. 「ソースコードの保存形式(UTF-8など)」は別レイヤ

.cpp/.h を UTF-8(BOMなし)で保存し、/utf-8 を付けるのは、コンパイラがソースや文字リテラルをどう解釈するかに影響します。

つまり、

  • 文字セット(Unicode/マルチバイト)= “実行時の文字列型やAPI側の方針”
  • ソースの文字コード(UTF-8など)= “ソースをどう読むか”

この2つは別物なので、混ぜると「どっちの話だっけ?」となりやすいです。

4-3. Shift-JIS はプレフィックスでは作れない

L""u8"" は Unicode系のリテラルを作る仕組みです。Shift-JIS(CP932)は型ではなくコードページ変換の結果なので、必要な場合は 変換関数で std::string(バイト列)として生成するのが一般的です。


5. どういう条件で使い分けるべきか(おすすめ運用)

5-1. Windows中心・今後も育てるプロジェクト(おすすめ)

  • Visual Studio:Unicode文字セット
  • ソース:UTF-8(BOMなし) + /utf-8
  • 方針:普段は std::string を UTF-8 として運用し、Windows API境界だけ std::wstring(UTF-16相当)へ変換

この運用は、教材的な std::string の感覚を残しつつ、Unicodeにも強くできます。

5-2. レガシー資産が Shift-JIS 前提で、短期で動かしたい

  • 既存のSJISテキスト(CSV/辞書/台詞)が大量にある
  • 古いツールや資産がSJIS前提

この場合でも「全体SJIS化」より、

  • I/O(読み込み/書き出し)だけSJIS
  • 内部はUTF-8/UTF-16へ寄せる
    の方が事故が少ないことが多いです。

5-3. ゲームで「1文字ずつ表示」などをしたい場合

UTF-8の std::string を使う場合、1バイト=1文字 ではないため、

  • UTF-8をデコードして「コードポイント」単位で進める(軽量)
  • さらに厳密にやるなら「グラフェム境界」(ICUなど)で進める
    といった方針が必要です。

最短まとめ(迷ったらこれ)

  • Unicode文字セットを選ぶ(Windows開発の基本)
  • ソースは **UTF-8(BOMなし)**で統一し、必要なら /utf-8
  • std::string は “UTF-8の器” と割り切って使う
  • Windows APIやファイルパスなど OS 境界だけ std::wstring に変換する
  • Shift-JIS は「プレフィックス」ではなく「変換で必要なときだけ作る」

付録:Visual Studioで「新規/保存ファイルの既定エンコーディング」をUTF-8(BOMなし)にする方法

Visual Studioでは、ファイルの既定保存エンコーディングを指定できます。Visual Studio 2022 v17.13以降では、IDEの設定として「既定の保存エンコーディング」を明示的に選べます。

方法A:Visual Studioのオプションで既定エンコーディングを指定(VS 2022 v17.13以降)

  1. Tools(ツール)> Options(オプション) を開く
  2. Environment(環境)> Documents(ドキュメント) を開く
  3. Save files with a specific encoding(特定のエンコーディングで保存)をオン
  4. Save encoding(保存エンコーディング)で UTF-8 without signature(UTF-8 BOMなし)を選ぶ
  5. OKで確定

この設定を入れると、以後の保存で指定したエンコーディングに揃いやすくなります。

補足:Microsoft Learn側でも同じ項目(Environment > Documents で “Save files with a specific encoding” を有効化して “Save encoding” を選ぶ)として案内されています。


方法B:プロジェクト単位で強制する(.editorconfig を使う)

IDEの個人設定ではなく、リポジトリ/プロジェクトのルールとして固定したい場合は .editorconfig が便利です。Visual StudioはEditorConfigをサポートしており、charset = utf-8 を指定できます。

例:プロジェクト直下に .editorconfig を作成

root = true

[*.{h,hpp,cpp,cxx,cc,inl,ipp}]
charset = utf-8
  • charset = utf-8 は通常 UTF-8(BOMなし) の意図になります。
  • BOMありにしたい場合は utf-8-bom を使う、という指定も可能です。

うまく設定できたか確認する方法

既存/新規ファイルを開いた状態で、Visual Studioの「エンコーディング指定で保存(Save with Encoding)」から、意図したエンコーディングになっているか確認できます(UTF-8 without signature など)。

タイトルとURLをコピーしました