web-dev-qa-db-ja.com

「使用目的で予約済み」の意味は何ですか?

注:これは c の質問ですが、C++の専門家がC++がCとは異なる表現を使用している理由や歴史的理由を提供できる場合に c ++ を追加しました。


C標準ライブラリの仕様には、この規範的なテキストであるC17 7.1.3予約済み識別子(エンファシスマイニング)があります。

  • アンダースコアと大文字または別のアンダースコアで始まるすべての識別子は、常にすべての使用のために予約されています
  • アンダースコアで始まるすべての識別子は、通常の名前空間とタグ名前空間の両方でファイルスコープを持つ識別子として使用するために常に予約されています。

現在、私は、尊敬されているさまざまなCの専門家によるSOの回答を読み続けています。

「任意の使用のために予約されている」とは、C言語自体の将来の拡張を除き、anyoneのために予約されていることを意味しませんか?実装はnotを使用できないことを意味します。

上記の2番目のフレーズは、単一のアンダースコアに関するものですが、実装に向けられているようですか?

一般に、C標準は、コンパイラベンダー/ライブラリの実装者が典型的なリーダーになることを期待するように書かれています-アプリケーションプログラマーではありません。

特に、C++には非常に異なる表現があります。

  • 二重アンダースコア(__)を含む名前、またはアンダースコアで始まり大文字(2.11)が続く各名前は、使用のために実装用に予約されています

C++識別子でアンダースコアを使用する際の規則は何ですか? を参照してください)

これはおそらくCとC++の混同であり、言語はここで異なりますか?

50
Lundin

C標準では、「予約済み」という用語の意味は、引用する箇条書きのすぐ下の7.1.3p2で定義されています。

他の識別子は予約されていません。 プログラムが予約されているコンテキストで識別子を宣言または定義している場合(7.1.4で許可されている場合を除く)、または予約された識別子をマクロ名として定義している場合、動作は未定義です。

重点鉱山:予約済み識別子は、実装ではなくprogramに制限を設けます。したがって、一般的な解釈(予約された識別子は実装で任意の目的に使用される可能性があります)はCにとって正しいものです。

私はC++標準に追いついておらず、それを解釈する資格がなくなったと感じています。

33
zwol

規格は主に実装者をガイドするために書かれていますが、asとしてプログラムを整形式にし、その効果を説明しています。これは、標準に準拠したコンパイラの基本的なdefinitionが、標準に準拠したプログラムに対して正しいことを行うためです。

厳密に準拠するプログラムは、この国際標準で指定されている言語とライブラリの機能のみを使用するものとします。..準拠するホスト実装は、厳密に準拠するプログラムを受け入れます。

個別に読むと、これはhugelyコンパイラの拡張を制限します。たとえば、その句のみに基づいて、コンパイラは独自の予約語のanyを定義するべきではありません。結局のところ、特定のコンパイラーが予約したいwantであっても、厳密に適合したプログラムに現れる可能性のあるWordは、コンパイラーの手を強制します。

ただし、標準は続いています。

準拠する実装には、厳密に準拠するプログラムの動作を変更しない限り、拡張機能(追加のライブラリ関数を含む)が含まれる場合があります。

それが重要な部分です。コンパイラ拡張機能は、非準拠プログラム(未定義の動作を含む、またはまったくコンパイルすべきではないプログラム)に影響を与えるような方法で記述する必要があり、コンパイルおよび余分なことを楽しみましょう。

そのため、「予約済み識別子」を定義する目的は、言語が実際にそれらの識別子を必要としない場合何かに識別子を提供することにより、実装に余地を与えることです。プログラムを不適合にします。コンパイラが__declspecを宣言の一部として認識できる理由は、__declspecを宣言に入れることは違法であるためです。したがって、コンパイラは何でもできます。

したがって、「あらゆる使用のために予約されている」ことの重要性は、そのような識別子を気にする意味を持つものとして扱うコンパイラーの能力について疑問を残さないことです。将来の互換性は比較的遠い関心事です。

C++標準も同様に機能しますが、Gambitについてはもう少し明示的です:

適合した実装には、整形式プログラムの動作を変更しない限り、拡張機能(追加のライブラリ関数を含む)が含まれる場合があります。この国際規格に従って不正な形式の拡張を使用するプログラムを診断するには、実装が必要です。 ただし、そうすれば、そのようなプログラムをコンパイルして実行できます。

言葉遣いの違いは、拡張機能がどのように機能するかについて明確になっているだけで、C++標準にまで及んでいると思います。それにもかかわらず、C標準では、実装が同じことを行うことを妨げるものはありません。 (そして、私たちは基本的に、__declspecを使用するたびにコンパイラが警告するという要件を無視します。)

16
Sneftel

CとC++の文言の違いに関して、参照としてここに自分の小さな研究を投稿しています。

  • 初期の K&R C第1版 には次のテキストがあります。

    ...ライブラリの関数によってのみ使用されることを意図した名前はアンダースコアで始まるため、ユーザーのプログラム内の名前と衝突する可能性は低くなります。

  • K&R 2ndエディションには、標準ライブラリに対応する付録Bが追加されました。

    アンダースコアと大文字または別のアンダースコアで始まる他のすべての識別子と同様に、アンダースコアで始まる外部識別子はライブラリで使用するために予約されています。

  • 初期のANSI Cドラフトと「C90」ISO 9899:1990には、現在のISO標準と同じテキストがあります。

  • ただし、最も初期のC++ドラフトには、@ hvdで指摘されているように、おそらくC標準の明確化として異なるテキストがあります。 ドラフト:1994年9月20日

    17.3.3.1.2グローバル名
    ...
    アンダースコアで始まり、大文字または別のアンダースコア(2.8)のいずれかで始まる名前は、すべての使用のために実装に予約されています

そのため、「任意の使用のために予約されている」という表現はANSI/ISO C90委員会によって考案されたのに対し、C++委員会は数年後、先行標準のK&R本と同様のより明確な表現を使用しました。


C99の根拠V5.10は、これを7.1.3の下で述べています。

また、実装者用に予約されているのは、アンダースコアで始まるすべての外部識別子と、アンダースコアで始まり、その後に大文字またはアンダースコアが続く他のすべての識別子です。これにより、ライブラリがその仕事を適切に行うために必要な多くの舞台裏の非外部マクロおよび関数を記述するための名前空間が与えられます。

これにより、委員会の意図は非常に明確になります。「あらゆる使用のために予約されている」とは、「実装者のために予約されている」ことを意味します。


また、注目すべき点として、現在のC標準には、6.2.5の他の場所に次の規範的なテキストがあります。

実装定義の拡張符号付き整数型もあります。 38)

有益な脚注38は次のように言っています:

38)実装定義のキーワードは、7.1.3で説明されているように、あらゆる使用のために予約された識別子の形式を持たなければならない。

12
Lundin

Cには、シンボルが定義を持つことができる複数のコンテキストがあります。

  • マクロ名のスペース、
  • マクロの引数の正式名のスペース(このスペースは、各関数のようなマクロに固有です)
  • 通常の識別子のスペース、
  • タグ名のスペース、
  • ラベルのスペース(このスペースは各機能に固有です)、および
  • 構造体/共用体メンバーのスペース(このスペースは各構造体/共用体に固有です)。

「任意の使用のために予約」とは、準拠プログラムのユーザーコードが使用できないことを意味します1 上記のコンテキストのいずれかで、アンダースコアで始まり、その後に大文字または別のアンダースコアが続くシンボル。 1つのアンダースコアで始まり、その後に小文字の数字または数字が続く識別子と比較してください。これは、アンダースコアで始まる識別子の2番目のクラスに分類されます。ユーザーコードcanは、これらの識別子をマクロ引数の名前、ラベル、または構造体/ユニオンメンバーの名前として使用できます。

「すべての使用のために予約されている」とは、実装がそのようなシンボルを使用できないことを意味するものではありません。予約の目的は、実装で定義された名前が準拠プログラムのユーザーコードで定義された名前と競合することを心配することなく、実装が自由に使用できる名前空間を提供することです。


1この規格は「使用できない」という意味ではありません。標準では、二重アンダースコアで始まる少数の名前のプログラムによる使用を推奨しています。たとえば、__STDC_VERSION____FILE____LINE__、および__func__を定義するには、準拠した実装が必要です。標準の2011バージョンは、__func__を参照する、おそらく準拠しているプログラムの例を提供します。

4
David Hammen

C規格により、実装は予約済み識別子に適合すると思われる任意の意味を付加できます。ほとんどの実装は、別の理由がない場合、予約された形式の認識されない識別子を他の認識された識別子と同じように扱います。

#ifdef __ACME_COMPILER
#define near __near
#else
#define near
#endif

int near foo;

コードがAcmeコンパイラーで処理されている場合(おそらくそのようなことをサポートしている場合)__near修飾子を使用して識別子fooを宣言しますが、必要または利点のない他のコンパイラーとも互換性がありますそのようなディレクティブの使用から。準拠する実装が__ACME_COMPILERを定義して__nearを解釈して「核ミサイルを発射する」ことを禁止することは何もありませんが、高品質の実装は上記のようなコードを壊すために邪魔をするべきではありません。実装が__ACME_COMPILERの意味を知らない場合、他の未知の識別子のように扱うことで、上記のような有用な構造をサポートできます。

2
supercat

それは数ヶ月遅れていますが、1つのポイントが残り、他は対処していません。

あなたの質問は反対方向から見ることができます。標準では、実装で(既に説明したように)_Fooのようなシンボルを使用できますが、さらに重要なことは、実装でfooを使用できないことです。後者はyourの使用のために予約されています。

理解するために、議論のために、将来のC標準で新しいキーワード_Fooが導入されたと仮定します。仮の実装ではすでにこのシンボルを使用していましたが、どうなりますか?

回答:

  1. 最初は、実装はまだ新しい標準を実装していません。実装されるまで、新しい標準には実用的な効果がありません。

  2. 後で新しい標準の実装の一部として実装は各_Foo_Barに静かに変更します。

問題ない。

実際、このように考えると、標準がそのような単語を予約する方法が、予約できる唯一の方法であると言えます。

0
thb