山かっこのGCCの実装には次のものが含まれます。なぜそれは以下に説明されているとおりでなければならないのですか?


11

このドキュメントのセクション2.6計算済みインクルードには、次の段落があります。

行が<トークンで始まり、>トークンを含むトークンストリームに展開される場合、<と最初の>の間のトークンが結合されて、含まれるファイル名が形成されます。トークン間の空白は1つのスペースに削減されます。その後、最初の<の後のスペースは保持されますが、閉じる>の前のスペースは無視されます。CPPは山かっこインクルードのルールに従ってファイルを検索します。

これは実装で定義されていることはわかっていますが、なぜGCCにとってこのようにする必要があるのですか?上記の強調表示された文を具体的に参照しています。

編集

上で引用したものの前の3番目の段落が次のことを言っていることに気づきました。

マクロを定義するときは注意が必要です。#defineテキストではなくトークンを保存します。プリプロセッサは、マクロがの引数として使用されることを知る方法がない#includeため、ヘッダー名ではなく通常のトークンを生成します。文字列定数に十分近い二重引用符を含むインクルードを使用する場合、これが問題を引き起こすことはほとんどありません。 ただし、山括弧を使用すると、問題が発生する可能性があります

ここでどんな問題が指摘されているか知っていますか?


6
おそらく、GCCの開発者は、ファイル名の末尾にスペースを含めることは忌まわしいことだと考えています。
user3386109

1
先頭と末尾にスペースがあるファイル名は、特にWindowsの場合、非常に扱いにくいものです。
レミールボー

1
そのように定義されているからといって、必ずしもそのように定義されなければならないという意味ではありません。規格では義務付けられていません。
eerorika

Visual Studioは、最初と最後の両方のスペースを削除するため、動作が異なります。HP aCCはgccのように動作します(互換性の理由から)。
Slimak

ドキュメントは、特に問題ではない場合(特に二重引用符を使用する場合は任意のスペースを使用できます)、コードがどうなるかを逆にではなく単に説明する場合があります。
rustyx

回答:


9

実装者は、この機能を実装するときに、あまり考えずに最も簡単な方法を選択したと思います。

2000-07-03(20年前!)に最初の実装が行われたようです。関連部分は(ソース)のようになります

  for (;;)
    {
      t = cpp_get_token (pfile);
      if (t->type == CPP_GREATER || t->type == CPP_EOF)
        break;

      CPP_RESERVE (pfile, TOKEN_LEN (t));
      if (t->flags & PREV_WHITE)
        CPP_PUTC_Q (pfile, ' ');
      pfile->limit = spell_token (pfile, t, pfile->limit);
    }

特に、トークン用のメモリを予約する前にCPP_GREATERトークン(つまり>)を検出するとブレークアウトします。トークンがバッファに書き込まれない場合にメモリを割り当てる必要がないため、これは理にかなっています。

次に、メモリが予約されたにのみ、プリプロセッサはトークンに先行する空白(t->flags & PREV_WHITE)があるかどうかを確認し、空白がある場合は空白文字をバッファに書き込みます。

その結果、中< foo / bar >だけ空白の前に、foo(それが最初の後に、である<、) /、およびbar保管されています。


素晴らしい、素晴らしい答え。私がGCCでコードの一部を見る機会があるのはこれが初めてです。これありがとう。
Ayrosa

しかし、条件if (t->flags & PREV_WHITE) CPP_PUTC_Q (pfile, ' ');がドキュメントでの発言と矛盾しているのではありませんか:「トークン間の空白はすべて単一のスペースに縮小されます; ...」?
Ayrosa
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.