[初級] C++: 文字コードのこと（2024年時点）

2024年時点、C++でプログラムを書く場合に知っているとよいと思う文字コードのこと
ASCII, JIS漢字, Shift_JIS, CP932, Unicode, UTF-16

:::note info
本記事の前提条件は以下の通りです。
* 初心者向け
* とは言っても、何らかのプログラムはそれなりに書けるけど、C とか C++ はちょっと、という人向け
* ざっくり概要しか説明しないので細かいことは気にしないでいただきたい
* Visual Studio 2013 くらい～
* Windowsプログラム (CUI, GUI)
* コードの検証
    * 開発環境: Visual Studio 2022, x64, Release ビルド
    * 実行環境: Windows 10
:::

:::note info
* 本記事は上から順番に読む前提となっている
:::

:::note info
* 「C++」と書いてあるが、本記事の内容としてはどの言語でもほぼ同じ
* 「Visual Studio 2013 くらい～」と書いてあるが、本記事の内容だと現在過去未来のどのバージョンでもほぼ同じ
* 「Windowsプログラム (CUI, GUI)」と書いてあるが、本記事の内容だとどの OS でもほぼ同じ
* CP932 についてはマイクロソフトの規格なのであしからず
:::

:::note info
参考文献など
* [ASCIIコード表 - IT用語辞典 e-Words](https://www.k-cube.co.jp/wakaba/server/ascii_code.html)
* [半角カナ - Wikipedia](https://ja.wikipedia.org/wiki/%E5%8D%8A%E8%A7%92%E3%82%AB%E3%83%8A)
* [JIS X 0201 - Wikipedia](https://ja.wikipedia.org/wiki/JIS_X_0201)
* [JIS漢字コード - Wikipedia](https://ja.wikipedia.org/wiki/JIS%E6%BC%A2%E5%AD%97%E3%82%B3%E3%83%BC%E3%83%89)
* [ISO/IEC 2022 - Wikipedia](https://ja.wikipedia.org/wiki/ISO/IEC_2022)
* [ISO-2022-JP - Wikipedia](https://ja.wikipedia.org/wiki/ISO-2022-JP)
* [Shift_JIS - Wikipedia](https://ja.wikipedia.org/wiki/Shift_JIS)
* [EUC-JP - Wikipedia](https://ja.wikipedia.org/wiki/EUC-JP)

* [とほほの文字コード入門 - とほほのWWW入門](https://www.tohoho-web.com/ex/charset.html#shift_jis)
* [Visual C++ のテキストと文字列 - Microsoft Lean](https://learn.microsoft.com/ja-jp/cpp/text/text-and-strings-in-visual-cpp?view=msvc-170)
* [コード ページ識別子 - Microsoft Lean](https://learn.microsoft.com/ja-jp/windows/win32/intl/code-page-identifiers)
:::

# ASCII コード
アメリカの規格化団体 (ANSI) が作ったコード体系。
0x00 - 0x7F の1バイトの中に、数字、アルファベットの小文字、大文字、基本的な記号、制御文字などが含まれている。
現時点で一般的に使われているどのコード体系でも、1バイトコードは基本的に ASCII コードと同じになっていると思われる。

:::note info
[ASCIIコード表 - IT用語辞典 e-Words](https://www.k-cube.co.jp/wakaba/server/ascii_code.html)
:::

# 半角カナ
0xA1-0xDF を半角カナのコードとした。
1バイトコードのこの領域は、他の言語の場合でも通常のアルファベット以外の文字が登録されて各言語ごとに使われている。
* `JIS X 0201` `ANK`

:::note info
JIS7 の場合、7 bit しか使えないので 8 bit 目を削る。その結果、'1' と 'ｱ' の区別がつかなくなるので、SI/SO などの制御コードを使って切り換えていた。
:::

:::note info
[半角カナ - Wikipedia](https://ja.wikipedia.org/wiki/%E5%8D%8A%E8%A7%92%E3%82%AB%E3%83%8A)
[JIS X 0201 - Wikipedia](https://ja.wikipedia.org/wiki/JIS_X_0201)
:::

# JIS漢字
基本的には日本産業規格 (JIS) が定めた文字コードのことであるが、プログラムを書いている立場としては、Shift_JIS コードに対しての　JIS 漢字コード、を指す場合の方が多い。
その場合の JIS 漢字としての特徴を以下に挙げる。
* それぞれ 7ビットの 2バイトコード
* `ISO/IEC 2022` に基づく `ISO-2022-JP` のことである

:::note info
`ISO/IEC 2022` では、1バイトコードと 2バイトコードを切り替える必要があり、JIS漢字では、KI/KO（漢字in/漢字out）などと呼ばれた制御コードを使っていた。
:::

:::note info
[JIS漢字コード - Wikipedia](https://ja.wikipedia.org/wiki/JIS%E6%BC%A2%E5%AD%97%E3%82%B3%E3%83%BC%E3%83%89)
[ISO/IEC 2022 - Wikipedia](https://ja.wikipedia.org/wiki/ISO/IEC_2022)
[ISO-2022-JP - Wikipedia](https://ja.wikipedia.org/wiki/ISO-2022-JP)
:::

# Shift_JIS
JIS漢字での 1バイトコードと 2バイトコードの切り替えなしに処理することを目的に作られた。
1バイト目に、それまで `ISO-2022-JP` の 1バイトコードとして未使用であった領域を利用し、2バイトコードであることを判定できるようになっている。
JIS漢字コードを領域ごとに「シフト」したものなので計算で変換可能。

:::note info
[Shift_JIS - Wikipedia](https://ja.wikipedia.org/wiki/Shift_JIS)
:::

# EUC-JP
UNIX系で使われていて20世紀には結構評判よかったように思うが、最近あまり使われていない。

:::note info
[EUC-JP - Wikipedia](https://ja.wikipedia.org/wiki/EUC-JP)
:::

# CP932
マイクロソフトの日本語用コードページ。
Shift_JIS をベースにしているが、独自拡張されている。
各メーカーが Shift_JIS を独自拡張して利用していたためにバラバラになっていたもの（機種依存文字）を、マイクロソフトが統合した。
このため、Shift_JIS にはない、下記文字集合が登録されている。
* NEC特殊文字「①②...ⅠⅡ..㍉㌔...などなど」
* NEC選定IBM拡張文字（ほとんどIBM拡張文字と重複）
* IBM拡張文字
* （それと、Windowsの外字）

マイクロソフトが統合したものは本当は `MS932` あるいは `Windows-31J` というのだが、マイクロソフト的には `CP932` と表記している。

:::note info
NEC特殊文字の一部など、`Shift_JIS-2004` によって同じ位置に追加されているので、Shift_JIS でも使えるようになっているものもある。
ただし、`Shift_JIS-2004` では、IBM拡張文字などには全く異なる文字が割り当てられているので注意が必要。
:::

# ANSI
 * アメリカの工業規格団体 (American National Standards Institute)、またその規格のこと
    * ASCII コードを制定した（当時は ASA）
    * このことから、ASCII コードを ANSI コードと言っている場合もあると思われる
 * マイクロソフトは MBCS も含めて ANSI 文字列、と言っている
     * シフト JIS を含む MBCS が ANSI 文字列と同じように、また混在した状態でも処理できるため、ひっくるめて ANSI 文字列と言っていると思われる
ようするに、同じ API が使えるんだから定義変えなくてもいいでしょ、ということである

:::note info
[Visual C++ のテキストと文字列 - Microsoft Lean](https://learn.microsoft.com/ja-jp/cpp/text/text-and-strings-in-visual-cpp?view=msvc-170)
:::

# Unicode
## UTF-8
現時点では最も一般的と思われるが、プログラムをする上ではあまり使わないので割愛。

## UTF-16
### Windows の UNICODE の内部表現はこれ
* L"ABC" で UTF-16 文字列となる

### 1文字 = 2バイトなわけではないので注意が必要
* サロゲートペア
    * 1文字が 4バイトになる
    * 世界中の文字を表現するのに 2バイトでは足りなかった...というオチ
    * JIS漢字だと、現状では第3水準、第4水準にしか現れない（たぶん）
    * 例えば「𩸽」（←コピペして UTF-16 でバイナリ表示してみて）
* 異体字
    * 異体字セレクタという仕組み自体にも何種類かあるが、漢字で使われるものは IVS というもので、1文字が 6バイトになる
    * 渡邊の「邊」など、異なる字体がいくつもある場合、フォントがすべてに対応するのは困難なため、代表の字体＋異体字コード、でフォントが対応している場合は異体字を表示し、対応していない場合は代表の字体を表示する、ということができるようになる
    * 例えば「葛󠄀」（←コピペして UTF-16 でバイナリ表示してみて）
* 結合文字
    * 「合成文字」といった方がわかりやすいが、後ろにくっつける文字のことを「結合文字」と言っている模様
    * 例えば「ポ」（←コピペして UTF-16 でバイナリ表示してみて）
    * 上記は「ポ」とは違い「ホ」と「゜」が合成されたものとなっている
このため 1文字が 4バイトある
    * 本来は発音記号（ダイアクリティカルマーク）などを表現するためのものと思われる
    * 何文字でも結合できる模様（この辺りの詳細はよくわからないのであしからず）

当然ながらこれらの組み合わせもあるので、もうなんだかよくわからない。