4
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Shift-JIS, UTF-8をC言語で扱うために文字コードについて調べた

Last updated at Posted at 2019-11-23

Shift-JIS, UTF-8をC言語で扱わないといけなかったけどわからなさ過ぎたので、文字コードとC言語での扱い方について調べたり考えたりした。
嘘は言ってないつもりですが、それでも間違ってたら優しく教えてくださるととても嬉しいです。
特に脚注の疑問が気になっているのでお気軽にぜひ...

文字コード

ASCIIコード

特徴

  • 半角英数と制御文字(改行コードとか)だけを表すための文字コード
  • 1バイト
  • 最上位bitは常に0(上位4bitは7まで)

例):
a → 61

https://en.wikipedia.org/wiki/ASCII より

Shift-JIS

特徴

  • 日本語を表現するために発明された文字コード
  • ASCII文字はそのまま使い、使われていないコード(最上位bitがA以降)に半角カタカナを割り振る → ASCII互換
  • 全角文字(平仮名など)の表現のために2バイトのコードを使う → 1~2バイトの可変長

例):
a → 61
ア → B1
あ → 82 A0

1バイト目("あ"の場合は"82")にASCIIで使われていない値が来た場合に2バイト文字と判断し、2バイト目も扱う。

Unicode

特徴

  • 全世界の文字を統一的に表現するための文字コード
  • 最大21bit
  • 複数の符号化方式がある(効率的なデータ保存のため?)
    • UTF-8
    • UTF-16
    • その他割愛

Unicode → UTF-8とか(符号化) → Unicodeのように使う

例):
a → U+0061
あ → U+3042

UTF-8

特徴

  • Unicodeの符号化方式
  • ASCII文字は1バイト、そのほかは2~4バイトの可変長で表現(日本語は3バイト) → ASCII互換

例):

文字 Unicode UTF-8
a U+0061 61
U+3042 E38182

文章の先頭につくBOM(Unicodeの符号化方式の判別用のマーク)は3バイトだが、必須でも推奨でもないのでなくてもいい。Excelで開くときにはBOMがないと問題が起こるらしい。

UTF-16

特徴

  • Unicodeの符号化方式
  • 基本は2バイト固定。2バイト以下で表せないものはサロゲートペアと呼び、2バイト×2の4バイトで表現する(ここは少し自信なし)
  • Windows標準で、C#のstringもUTF-16らしい1

例):

文字 Unicode UTF-16
a U+0061 FF41
U+3042 3042
サロゲートペアについては以下に例がある。

Unicode番号が16進数で10000以上の文字を、UTF-8(およびUTF-16)では1 符号単位で表現することができない。
そのため、Unicode番号D800〜DBFFとDC00〜DFFFの組み合わせで表現した仕組み。
https://qiita.com/deco/items/81338e744945f9fef5b2 より

C言語での表現

今までのまとめ。"あ"と"a"の各符号化方式。

文字 Unicode UTF-8 Shift-JIS UTF-16
a U+0061 61 61 FF41
U+3042 E38182 82A0 3042

一方、C言語では

  • charは1バイト。
  • wchar_tsetlocale(LC_ALL, "jpn")して日本環境にすると2バイト固定。
  • wchar_tは環境によりバイト数が違う。Windowsだと一般に2バイト、Andoroidだと4バイトだったりするよう。

よって"あaあ"という文字列を表現した場合、以下のように認識される。

符号化方式 バイト列
char UTF-8 E3 81 82 61 E3 81 82
char Shift-JIS 82 A0 61 82 A0
char UTF-16 30 42 FF 41 30 42
wchar_t UTF-8 E381 8261 E381 82002
wchar_t Shift-JIS 82A0 6100 82A02
wchar_t UTF-16 3042 FF41 3042
※脚注がついているものは間違っている可能性大です。教えてください。

結論

  • 結合するだけとかで、文字数や各文字を識別する必要がないならcharだけでいい。

  • 文字数を気にしたい場合はShift-JISとUTF-16ならwchar_tが完璧。

  • UTF-8で文字数識別が必要とかになったらどうするんだろう。char32_tとか調べきれてない型を使うのだろうか。

  • UTF-8とShift-JISの変換に関して「MultiByteToWideChar()でワイド文字(Unicode)に直してからWideCharToMultiByte()でマルチバイト文字に戻す」ということ文を見た。Windowsのページなので、これはたぶん「char → UTF-16(wchar_t) → char」という意味の、"Unicode=UTF-16過激派"の表現なんだなと思った。どこかのブログに「microsoftがUnicodeと言ったらUTF-16のことである」って書いてあったし、紛らわしい。

  1. メモ帳を保存するときの文字コードの選択肢にあるUnicodeはUTF-16(リトルエンディアン)のこと指しているらしく、文字コード初学者にとって非常に紛らわしい。

  2. E38182 61(UTF-8の"あa")のような奇数バイトの文字がwchar_tに入った場合に、E381 8200 6100 or E381 8261になるのかわからなかったです。誰か教えてください... 2

4
2
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?