C++ '03 Standard 2.3/1によると:
他の処理が行われる前に、次の3文字のシーケンス(「トライグラフシーケンス」)のいずれかが出現するたびに、表1に示す単一の文字に置き換えられます。
_---------------------------------------------------------------------------- | trigraph | replacement | trigraph | replacement | trigraph | replacement | ---------------------------------------------------------------------------- | ??= | # | ??( | [ | ??< | { | | ??/ | \ | ??) | ] | ??> | } | | ??’ | ˆ | ??! | | | ??- | ˜ | ----------------------------------------------------------------------------
_
実際には、コードprintf( "What??!\n" );
は、_What|
_が_??!
_文字に置き換えられる3文字表記シーケンスであるため、_|
_を出力します。
私の質問は、トライグラフを使用する目的は何ですか?トライグラフを使用する実用的な利点はありますか?
[〜#〜] upd [〜#〜]:一部のヨーロッパのキーボードには句読点がすべて含まれていないため、米国外のプログラマーは日常生活で3文字表記を使用しなければならないという回答がありましたか?
PD2:Visual Studio 2010では、トライグラフのサポートがデフォルトでオフになっています。
この質問(密接に関連する有向グラフについて) には答えがあります。
ISO 646文字セットにはC構文のすべての文字が含まれていないという事実に要約されます。そのため、文字を処理できないキーボードとディスプレイを備えたシステムがあります(これらは非常にまれだと思いますが)最近)。
一般に、それらを使用する必要はありませんが、実際に発生した問題については、それらについて知る必要があります。トライグラフは、 '?
'文字にはエスケープシーケンスがあります。
'\?'
したがって、サンプルの問題を回避する方法は2つあります。
printf( "What?\?!\n" );
printf( "What?" "?!\n" );
ただし、2つの「?」を入力するときは覚えておく必要があります。あなたがトライグラフを始めているかもしれないキャラクター(そして、私が考えていることは決してありません).
実際には、3文字表記と2文字表記は日常的にまったく心配することはありません。しかし、数年に一度、それらに関連するバグに遭遇するため、それらに注意する必要があります(そして、残りの時間を彼らの存在を呪うことに費やします)。コンパイラーが3文字表記または2文字表記に遭遇したときに警告(またはエラー)するように構成できればいいので、意図的に対処する必要があるものがあることがわかりました。
また、完全を期すために、ダイグラフはトークンとして処理されるため、それほど危険ではありません。したがって、文字列リテラル内のダイグラフは、ダイグラフとして解釈されません。
C/C++プログラムの句読点のさまざまな楽しみに関する素敵な教育(間違いなく髪を引っ張ってしまう3文字表記のバグを含む)については、 Herb SutterのGOTW#86記事 をご覧ください。
補遺:
GCCはデフォルトで3文字表記を処理しない(および警告する)ようです。他の一部のコンパイラには、トライグラフのサポートをオフにするオプションがあります(IBMなど)。マイクロソフトは、VS2008で(-Wallなどを使用して)明示的に有効にする必要がある警告(C4837)のサポートを開始しました。
The C++ Programming Language
Special Edition、829ページから
ASCII特殊文字
[
、]
、{
、}
、|
、および\
が占めるISOによってアルファベットとして指定された文字セットの位置ほとんどのヨーロッパの国のISO-646文字セットでは、これらの位置は英語のアルファベットにはない文字で占められています。真に標準的な最小文字セットを使用して、各国語の文字を移植可能な方法で表現できるようにするために、3文字のセットが提供されます。これはプログラムの交換に役立ちますが、プログラムを読みやすくすることはできません。当然、この問題の長期的な解決策は、C++プログラマーがネイティブ言語とC++の両方を適切にサポートする機器を入手することです。残念ながら、これは一部の人にとっては実行不可能であるように思われ、新しい機器の導入はイライラするほど遅いプロセスになる可能性があります。
今日の子供たち! :-)
はい、IBM 3270ターミナルなどの外部機器。覚えていれば、3270には中括弧はありません! IBM mini /メインフレームでCを記述したい場合、toを使用して、すべてのブロック境界に惨めなトライグラフを使用します。幸いなことに、私はCのソフトウェアをemulateに書くだけで、実際にCソフトウェアを書く必要はありませんでしたシステム/ 36。
「P」キーの横を見てください。
うーん。わかりにくい。 「キャリッジリターン」の横に追加のボタンがあり、逆方向に持っている場合があります。「[」/「]」ペアが欠落していた可能性があります。とにかく、このキーボードはCを書かなければならないと悲しむでしょう。
また、これらの端末は、IBMの「ネイティブ」メインフレーム文字セットであるASCII(リマインダーについてPavel Minaevに感謝)ではなく、EBCDICを表示します。
一方、GNU Cガイドは次のように述べています。 "この脳の損傷は必要ありません。" gccコンパイラは、この "機能"をデフォルトで無効のままにします。
これらは、C++の基本的な文字セットの文字の一部を欠いているシステムで使用するためのものです。言うまでもなく、そのようなシステムは非常にまれです。
C++ 0xで削除するためのトライグラフが提案されています。とはいえ、それらを支持する強力な議論がまだあるようです。これについては、C++委員会のペーパー N291 を参照してください。どうやら、EBCDICはそれらが必要とされる1つの主要な拠点です。
90年代前半にメインフレームからPL/1プログラムをPC上で実行/コンパイル/デバッグするために変換するのに役立つ3文字表記を見てきました。
彼らはPL/I to Cコンパイラを使用してPCでPL/Iを編集することに手を出し、中括弧をサポートしていないメインフレームに戻ったときにコードが動作することを望んでいました。私は彼らが次のようなマクロを使用できることを提案しました
#def BEGIN {
#def END }
または友好的なPL/Iの代替として
#def BEGIN ??<
#def END ??>
そして、彼らが本当に空想を得たいなら、彼らは試みることができました
#ifdef MAINFRAME
#def BEGIN ??<
#def END ??>
#else
#def BEGIN {
#def END }
#endif
そして、プログラムはPascalで書かれたように見えます。彼らはただ私を面白く見ただけで、その日は私と話をしませんでした。私は彼らを責めるとは思わない。 :)
トライグラフではなく努力を殺したのは、プラットフォーム間のIOシステムの違いでした。PC上のファイルを開くことは、あまりにも多くのクラッジを導入していたメインフレームとは大きく異なりました。両方で同じコードを実行し続けるために。
ヨーロッパのキーボードの中には、通常のアルファベット文字のキーが必要なため、米国のキーボードにあるすべての句読点文字を持たない(しなかった?)そのため、たとえば(これを構成する)スウェーデン語のキーボードには、中括弧がある場所にAリングがあります。
これらのユーザーに対応するために、3文字表記は最も一般的なASCII文字のみを使用して句読点を入力する方法です。
それらは主に歴史的な理由でそこにあります。最近では、ほとんどの言語のほとんどの最新キーボードでこれらすべての文字にアクセスできますが、これは一部のヨーロッパのキーボードではかつて問題でした。これがトライグラフが発明された理由です。
目的がわからない場合は、使用しないでください。
ただし、コード内で誤って意図せずに使用する可能性があるため、それらを認識しておくのは良いことです。
主に1989年にC標準により導入されたため、一部のマシンでトリグラフがマップする文字の存在に問題があったためです。 1998年にC++標準が公開された頃には、3文字表記の必要性はそれほど大きくありませんでした。これらはCのいぼです。それらは、C++の場合と同じくらいいぼです。特に英語圏以外では、C言語に追加する必要がありました。