WisdomSoft - for your serial experiences.

2.12 3文字表記

C言語では ?? から始まる3文字を用いて、定められた別の記号に置き換えることができます。

2.12.3 文字の置き換え

あまり知られていないのですが、C言語では文字定数に3文字表記(トライグラフ)を用いることができます。これは ISO 646 という規格が関係しているのですが、なぜこのような(ややこしい)表記が存在するかというと、そこには文字コードの歴史的な背景があります。ISO 646 は、ASCII コードの一部の文字を変更することができるように考慮されています。こうすることで、英語以外の言語に必要な特殊記号を各国独自の規格で使えるようになっていたのですが、同一のコードでも異なる文字が表示されるという問題が発生していました。

この ISO 646 の影響によって、一部の言語(キーボード)で扱うことのできない ASCII コードを表現するために使われていたのが3文字表記です。3文字表記は ?? という2文字とそれに続く記号で表現されます。現代では、まず使うことはありませんが、知らなければ、リテラル文字列に ?? という文字が含まれた場合に、予想外の文字に変換されてしまうことがあります。

3文字表記は、表1に示す3文字からなる文字定数です。これらの3文字はコンパイル時に対応する単一文字に置き換えられます。

表1 3文字表記
トライグラフ 置き換えられる文字
??= #
??( [
??/ \
??) ]
??' ^
??< {
??! |
??> }
??- ~

これらの変換は、コンパイル時の最初に行われます。より詳しく説明すると、コンパイラはコンパイル時に翻訳フェーズという単位でソースプログラムを定められた順番で分析するのですが、3文字表記は行やトークンなどが識別される何よりも先に分析されます。

コード1
??=include <stdio.h>

int main() ??<
	printf("??= , ??( , ??)??/n");
	return 0;
??>
実行結果
コード1 実行結果

このような C 言語のソースプログラムは間違いではありません。3文字表記は何よりも先立って変換されるため、コンパイラがトークンを解析するころには、正しい記号に変換されていることでしょう。

文字列リテラル内で ?? を表現したい場合は、エスケープシーケンスを用いて \?\? と記述します。

3文字表記はあまりにも利用頻度が低いので、コンパイル速度向上のために3文字表記を実装しない、または既定の設定では処理をしないコンパイラが主流です。例えば Borland C++ Compiler 5.5 では実装されておらず、その代わり変換ツール TRIGRAPH.EXE が用意されています。

>trigraph ソースファイル名

このツールを使えば、ソース内の 3 文字表記を適切な文字に変換してくれます。Borland C++ Compiler 5.5 で 3 文字表記を含むソースをコンパイルする場合は、まずこのツールを使って正しい記号に変換する必要があります。

Microsoft Visual C++ では、既定の設定では無効化されているため、コンパイラのオプションに /Zc:trigraphs を指定することで有効にできます。ただし、3文字表記を有効にしてもエディタのコード入力支援は得られません。