40

私は長い間 C で作業してきたので、コンパイラが一般的に an の先頭にアンダースコアを追加するという事実がextern理解されています... しかし、今日の別の SO の質問で、アンダースコアが追加される本当の理由について疑問に思いました。ウィキペディアの記事によると、その理由は次のとおりです。

ランタイム言語サポートからの貢献との衝突を避けるために、すべての外部スコープ プログラム識別子の先頭にアンダースコアを付加することは、C コンパイラにとって一般的な方法でした。

これには少なくとも真実の核があると思いますが、すべてのexternにアンダースコアが追加された場合、衝突を防ぐのにあまり役に立たないため、実際には質問に答えていないようです.

先頭のアンダースコアの理論的根拠について、誰かが良い情報を持っていますか?

creat()追加されたアンダースコアは、Unixシステム コールが「e」で終わらない理由の一部ですか? 一部のプラットフォームの初期のリンカーでは、名前が 6 文字に制限されていると聞いたことがあります。その場合、外部名の前にアンダースコアを追加するのは、まったくクレイジーなアイデアのように思えます (今、私は 5 文字しか操作できません...)。

4

5 に答える 5

22

Cコンパイラでは、実行時言語サポートからの寄与との衝突を回避するために、すべての外部スコーププログラム識別子の前に先頭の下線を付けるのが一般的な方法でした。

ランタイムサポートがコンパイラによって提供される場合は、代わりにランタイムサポートのいくつかの外部識別子にアンダースコアを追加する方が理にかなっていると思います。

Cコンパイラが最初に登場したとき、これらのプラットフォームでのCでのプログラミングの基本的な代替手段は、アセンブリ言語でのプログラミングでした。アセンブラとCで記述されたオブジェクトファイルをリンクすることは有用でした(場合によってはまだ有用です)。外部C識別子に追加されたアンダースコアは、独自のアセンブリコード内の識別子との衝突を回避するためのものでした。

GCCのasmラベル拡張も参照してください。この付加されたアンダースコアは、名前マングリングの単純な形式と見なすことができることに注意してください。C++のようなより複雑な言語は、より複雑な名前マングリングを使用しますが、ここから始まります。)

于 2010-04-13T09:24:08.123 に答える
6

C コンパイラが常にすべてのシンボルの前にアンダースコアを追加した場合、スタートアップ/C ランタイム コード (通常はアセンブリで記述されます) は、アンダースコアで始まらないラベルとシンボル (シンボル 'start など) を安全に使用できます。 ')。

c コードで start() 関数を記述しても、object/asm 出力では _start として生成されます。(この場合、C コードがアンダースコアで始まらないシンボルを生成する可能性はないことに注意してください)。彼/彼女のグローバル変数/ラベル。

そのため、リンカーは名前の競合について文句を言うことはなく、プログラマーは満足しています。:)

以下は、出力形式でアンダースコアを先頭に追加するコンパイラの慣行とは異なります。

このプラクティスは、後に C および C++ 言語標準の一部として成文化されました。この標準では、先頭のアンダースコアの使用は実装のために予約されていました。

これは、c システム ライブラリおよびその他のシステム コンポーネントに対して従う規則です。(および __FILE__ などの場合)。

(このような記号 (例: _time) は、生成された出力で 2 つの先頭のアンダースコア (__time) になる場合があることに注意してください)

于 2010-04-13T18:46:11.373 に答える
3

私がよく耳にするのは、名前の競合を避けるためだということです。他の extern 変数ではなく、ライブラリを使用するときにユーザー コードの変数名と競合しないようにするためです。

于 2010-04-13T06:47:35.177 に答える
3

main 関数は、実行可能ファイルの実際のエントリ ポイントではありません。一部の静的にリンクされたファイルには、最終的に main を呼び出す実際のエントリ ポイントがあり、それらの静的にリンクされたファイルは、アンダースコアで始まらない名前空間を所有しています。私のシステムの /usr/lib には、gcrt1.o、crt1.o、dylib1.o などがあります。それらのそれぞれには、最終的に「_main」エントリポイントを呼び出すアンダースコアのない「開始」関数があります。これらのファイル以外のすべてのファイルには、外部スコープがあります。歴史は、すべての C が外部と見なされていたプロジェクトで、アセンブラーと C が混在していたことに関係しています。

于 2010-04-13T07:27:26.640 に答える
2

ウィキペディアから:

ランタイム言語サポートからの貢献との衝突を避けるために、C コンパイラがすべての外部スコープ プログラム識別子の先頭にアンダースコアを追加するのが一般的でした。さらに、C/C++ コンパイラが変換プロセスの一部として外部リンケージに名前を導入する必要がある場合、これらの名前は、複数の先頭または末尾のアンダースコアの組み合わせで区別されることがよくありました。

このプラクティスは、後に C および C++ 言語標準の一部として成文化されました。この標準では、先頭のアンダースコアの使用は実装のために予約されていました。
于 2010-04-13T06:54:20.297 に答える