web-dev-qa-db-ja.com

Cでは二重下線(__const)はどういう意味ですか?

extern int ether_hostton (__const char *__hostname, struct ether_addr *__addr)
 __THROW;

Linuxボックスの/usr/include/netinet/ether.hで上記の関数定義を見つけました。

Const(キーワード)、addr(識別子)、そして最後に__THROWの前にある二重アンダースコアの意味を誰かが説明できますか。

47
Deepak

Cでは、アンダースコアで始まり、その後に大文字または別のアンダースコアが続くシンボルは、実装用に予約されています。 Cのユーザーとして、予約されたシーケンスで始まるシンボルを作成しないでください。 C++では、制限はより厳格です。ユーザーは二重アンダースコアを含む記号を作成できません。

与えられた:

_extern int ether_hostton (__const char *__hostname, struct ether_addr *__addr)
__THROW;
_

___const_表記は、このコードで使用されているコンパイラがプロトタイプ表記をサポートしているが、C89標準キーワードconstを正しく理解していない可能性を可能にするためにあります。 autoconfマクロは、コンパイラがconstをサポートしているかどうかを確認できます。このコードは、そのサポートがない破損したコンパイラで使用できます。

___hostname_および___addr_を使用することは、ヘッダーのユーザーであるあなたにとっての保護手段です。 GCCおよび_-Wshadow_オプションを使用してコンパイルする場合、ローカル変数がグローバル変数をシャドウするとコンパイラーは警告を表示します。関数が___hostname_の代わりにhostnameのみを使用し、hostname()と呼ばれる関数がある場合、シャドウイングが発生します。実装用に予約されている名前を使用することにより、正当なコードと競合することはありません。

___THROW_を使用するということは、状況によっては、ある種の「スロー仕様」でコードを宣言できることを意味します。これは標準Cではありません。 C++に似ています。ただし、ヘッダーの1つ(またはコンパイラー自体)が___THROW_を空、または標準C構文のコンパイラー固有の拡張に定義している限り、コードはCコンパイラーで使用できます。


C規格のセクション7.1.3(ISO 9899:1999)は次のように述べています。

7.1.3予約済み識別子

各ヘッダーは、関連する副次句にリストされているすべての識別子を宣言または定義し、オプションで、関連する将来のライブラリ方向副次句にリストされている識別子と、任意の使用またはファイルスコープ識別子としての使用のために常に予約されている識別子を宣言または定義します。

—アンダースコアおよび大文字または別のアンダースコアで始まるすべての識別子は、常に使用するために予約されています。

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

—関連するヘッダーのいずれかが含まれている場合、次の副次句(将来のライブラリの指示を含む)の各マクロ名は、指定されたとおりに使用するために予約されています。特に明記されていない限り(7.1.4を参照)。

—次の副次句のいずれかで外部リンケージを持つすべての識別子(将来のライブラリの指示を含む)は、外部リンケージを持つ識別子として使用するために常に予約されています。154)

—次の副次節(将来のライブラリの指示を含む)にリストされたファイルスコープを持つ各識別子は、マクロ名として、および関連するヘッダーのいずれかが含まれる場合は同じ名前空間のファイルスコープを持つ識別子として使用するために予約されています。

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

プログラムが(_#undef_を使用して)上記の最初のグループの識別子のマクロ定義を削除する場合、動作は未定義です。

脚注154)外部リンケージ付きの予約済み識別子のリストには、errno、_math_errhandling_、setjmp、および_va_end_が含まれます。


C++識別子でアンダースコアを使用する場合の規則は何ですか ;も参照してください。多くの同じルールがCとC++の両方に適用されますが、この回答の冒頭で述べたように、埋め込まれた二重アンダースコアルールはC++のみにあります。

69

アンダースコアが2つ付いた名前は、実装で使用するために予約されています。これは、必ずしも内部的であることを必ずしも意味しませんが、多くの場合内部的です。

アイデアは、__で始まる名前を使用することは許可されていないため、実装ではマクロ展開などの場所や構文拡張の名前(__gcnewなど)で自由に使用できます。はC++の一部ではありませんが、MicrosoftはそれをC++/CLIに追加して、既存のコードにint __gcnew;のようなものが含まれていて、コンパイルが停止すると確信しています)。

これらの特定の拡張機能、つまり__constの意味を調べるには、特定のコンパイラ/プラットフォームのドキュメントを参照する必要があります。この特定のケースでは、おそらくドキュメントのプロトタイプを検討する必要があります(例 http://www.kernel.org/doc/man-pages/online/pages/man3/ether_aton.3.html )関数のインターフェイスになり、実際のヘッダーに表示される__constおよび__THROW装飾を無視します。

19
Logan Capaldo

一部のライブラリの慣例により、これは特定のシンボルが内部使用のためのものであり、ライブラリのパブリックAPIの一部であることを意図していないことを示しています。

3
Rob H

__constのアンダースコアは、このキーワードがコンパイラ拡張であることを意味し、それを使用することは移植性がありません(constキーワードは後のリビジョンでCに追加されたと思います89)。 __THROWもある種の拡張機能です。gccを使用すると__attribute __(something)に定義されると思いますが、確認するのが面倒でわかりにくいです。 __addrは、プログラマが意味するものであれば何でも意味します。単なる名前です。

2
Caotic