TL;DR
Unicode の文字を 8 ビットのバイトの列で表す文字エンコーディング。1 文字を 1〜4 バイトで表し、ASCII と互換性がある。RFC 3629 で定められている。
なぜ必要か
RFC 3629 によると、U+0000 から U+007F までの文字は US-ASCII と同じ 1 バイトの値になるので、ASCII だけの文字列はそのまま正しい UTF-8 の文字列でもある。また、ASCII のバイト値はマルチバイトの列の中に現れないので、ASCII のバイトを解析するソフトウェアでも UTF-8 を安全に扱える。
仕組み
扱う範囲は U+0000 から U+10FFFF までで、UTF-16 のサロゲートに使う U+D800 から U+DFFF は除かれる。コードポイントの範囲によって、使うバイト数と先頭のビットの形が決まる。
| コードポイントの範囲 | バイト数 | ビットの形 |
|---|---|---|
| U+0000〜U+007F | 1 | 0xxxxxxx |
| U+0080〜U+07FF | 2 | 110xxxxx 10xxxxxx |
| U+0800〜U+FFFF | 3 | 1110xxxx 10xxxxxx 10xxxxxx |
| U+10000〜U+10FFFF | 4 | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx |
各範囲は重ならないので、1 つの文字の正しい表し方は 1 つに決まる。C0、C1、F5〜FF のバイト値は、正しい UTF-8 には現れない。
注意点
RFC 3629 は、デコーダが不正な列をデコードしないよう求めている。必要以上に長い表し方(たとえば C0 80 を U+0000 と読む)を受け入れると、検査をすり抜けられてしまう。RFC は、2001 年に /../ を長い表し方で書き換えた攻撃が Web サーバに広く行われたことを例に挙げている。