C ++のTrigraphシーケンスの目的は?
質問
C ++ '03 Standard 2.3 / 1に準拠:
他の処理が行われる前に、次の3文字のシーケンス(“ trigraphシーケンス”)のいずれかが出現するたびに、表1に示す単一の文字に置き換えられます。
---------------------------------------------------------------------------- | trigraph | replacement | trigraph | replacement | trigraph | replacement | ---------------------------------------------------------------------------- | ??= | # | ??( | [ | ??< | { | | ??/ | \ | ??) | ] | ??> | } | | ??’ | ˆ | ??! | | | ??- | ˜ | ----------------------------------------------------------------------------
実際には、コード printf(&quot; What ??!\ n&quot;);
は、 ??!
は、 |
文字に置き換えられる3文字表記シーケンスです。
トライグラフを使用する目的は何ですか?トライグラフを使用する実用的な利点はありますか?
UPD :一部のヨーロッパのキーボードには句読点がすべて含まれていないため、米国以外のプログラマーは日常生活で3文字表記を使用する必要があるという回答がありましたか?
UPD2 :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など)。 Microsoftは、VS2008で(-Wallなどを使用して)明示的に有効にする必要がある警告(C4837)のサポートを開始しました。
他のヒント
The C ++ Programming Language
Special Edition、829ページから
ASCII特殊文字
[
、]
、{
、}
、|
、および\
は、ISOによりアルファベットとして指定された文字セットの位置を占めます。ほとんどのヨーロッパ各国のISO-646文字セットでは、これらの位置は英語のアルファベットにはない文字で占められています。真に標準的な最小文字セットを使用して、各国語の文字を移植可能な方法で表現できるようにするために、3文字表記のセットが提供されます。これはプログラムの交換には役立ちますが、プログラムを読みやすくすることはできません。当然、この問題に対する長期的な解決策は、C ++プログラマーがネイティブ言語とC ++の両方を適切にサポートする機器を入手することです。残念ながら、これは一部の人にとっては実行不可能であると思われ、新しい機器の導入はイライラするほど遅いプロセスになる可能性があります。
今日の子供たち! :-)
はい、IBM 3270ターミナルなどの外部機器。覚えていれば、3270には中括弧はありません! IBMミニ/メインフレームでCを記述したい場合は、すべてのブロック境界に惨めな3文字表記を使用する必要がありました。幸いなことに、私はCでソフトウェアを書いて一部のIBMミニコンピューター機能をエミュレートするだけでよく、実際にはSystem / 36でCソフトウェアを 書かないでください。
&quot; P&quot;の横を見てください。キー:
うーん。わかりにくい。 「キャリッジリターン」の横に追加のボタンがあり、逆方向に移動する場合があります。「[」 /&quot;]&quot;欠落していたペア。とにかく、このキーボードはCを書かなければならないと悲しむでしょう。
また、これらの端末はIBMの「ネイティブ」であるEBCDICを表示します。 ASCIIではなくメインフレームの文字セット(リマインダーについてはPavel Minaevに感謝)。
一方、GNU Cガイドが言うように:「この脳の損傷は必要ありません。」 gccコンパイラは、この「機能」を残します。デフォルトでは無効になっています。
これらは、C ++の基本文字セットに含まれる文字の一部が欠けているシステムで使用するためのものです。言うまでもなく、そのようなシステムは非常にまれです。
C ++ 0xで削除するためのトライグラフが提案されています。とはいえ、まだそれらを支持する強い議論があるようです-C ++委員会の論文 N2910 でこれについて説明しています。どうやら、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リングがあります。
これらのユーザーに対応するために、トライグラフは最も一般的なASCII文字のみを使用して句読点を入力する方法です。
主に1989年にC標準によって導入されたため、一部のマシンでトリグラフがマップする文字の存在に問題があったためです。 1998年にC ++標準が公開された頃には、3文字表記の必要性はそれほど大きくありませんでした。それらはCのいぼです。それらは、C ++の場合と同じくらいいぼです。特に英語圏以外では、それらが必要でした。そのため、Cに追加されました。
それらは主に歴史的な理由で存在しています。最近では、ほとんどの言語のほとんどの最新キーボードでこれらすべての文字にアクセスできますが、これはヨーロッパのキーボードでかつては問題でした。これがトライグラフが発明された理由です。
それらの用途がわからない場合は、使用しないでください。
ただし、コード内で誤って意図せずに使用してしまう可能性があるため、それらを認識しておくのは良いことです。