web-dev-qa-db-ja.com

Cで静的関数と変数を使用する理由

Cで、ファイル内の変数のスコープ制限としてstaticキーワードを使用することについて疑問に思います。

私が見ているようにCプログラムを構築する標準的な方法は次のとおりです。

  • 関数と変数を定義するcファイルの束があります。スコープはstaticで制限されている可能性があります。
  • 他のcファイルが使用できるように、対応するcファイルの関数と場合によっては変数を宣言するhファイルの束があります。プライベート関数と変数はhファイルで公開されていません。
  • すべてのcファイルは個別にoファイルにコンパイルされます。
  • すべてのoファイルはアプリケーションファイルにリンクされています。

とにかく変数がhファイルで公開されていない場合、gobalをstaticとして宣言する2つの理由がわかります。

  • 1つは読みやすさのためです。変数が他のファイルでアクセスされていないことを、私を含む将来の読者に知らせてください。
  • 2つ目は、別のcファイルが変数をexternとして再宣言しないようにすることです。リンカは、変数がexternstaticの両方であることを嫌うと思います。 (他の誰かが所有する変数をexternとして再宣言するファイルのアイデアは嫌いですが、それは大丈夫ですか?)

他の理由はありますか?

static関数についても同じことが言えます。プロトタイプがhファイルで公開されていない場合、他のファイルはとにかく関数を使用しない可能性があるので、なぜそれをstaticと定義するのですか?同じ2つの理由がわかりますが、それ以上はわかりません。

26
Gauthier

他のリーダーへの通知について話すときは、コンパイラー自体をリーダーと見なしてください。変数がstaticと宣言されている場合、最適化が開始される程度に影響を与える可能性があります。

static変数をexternとして再定義することは不可能ですが、コンパイラーは(いつものように)自分をぶら下げるのに十分なロープを提供します。

あるファイルにstatic int foo;を書き込み、別のファイルにint foo;を書き込むと、これらは異なる変数と見なされます同じ名前とタイプであるにもかかわらず、コンパイラは文句を言いませんが、おそらく後でコードを読み取ったりデバッグしたりしようとすると、非常に混乱します。 (2番目のケースでextern int foo;と書くと、他の場所で非静的int foo;を宣言しない限り、リンクに失敗します。)

グローバル変数がヘッダーファイルに表示されることはめったにありませんが、表示される場合はexternと宣言する必要があります。そうでない場合、コンパイラによっては、そのヘッダーを含むすべてのソースファイルが変数の独自のコピーを宣言するリスクがあります。これにより、リンク障害(多重定義シンボル)が発生し、最悪の場合、いくつかの紛らわしいシャドウイングが発生します。

26
crazyscot

ファイルレベルで変数staticを宣言することにより(関数内のstaticは異なる意味を持ちます)、他のユニットがそれにアクセスすることを禁止します。別のユニット(externで宣言)内で変数を使用しようとすると、リンカーはこのシンボルを見つけられません。

9
qrdl

static関数を宣言すると、関数の呼び出しは「ニアコール」であり、理論的には「ファーコール」よりもパフォーマンスが向上します。あなたはより多くの情報のためにグーグルすることができます。 これ は私が簡単なグーグル検索で見つけたものです。

8
INS

ファイルacで変数fooを静的にせずに宣言し、ファイルbcで変数fooを静的にせずに宣言すると、両方が自動的にexternになります。つまり、両方を初期化するとリンカーが文句を言い、そうでない場合は同じメモリ位置を割り当てる可能性があります。文句はありません。コードのデバッグを楽しんでください。

静的にせずにファイルacに関数foo()を記述し、静的にせずにファイルbcに関数foo()を書き込むと、リンカーは文句を言うかもしれませんが、そうでない場合、foo()へのすべての呼び出しは同じ機能。コードのデバッグを楽しんでください。

1
gnasher729

グローバル変数が静的であると宣言されている場合、コンパイラーは、そうでない場合よりも優れた最適化を行うことができる場合があります。コンパイラは、変数が他のソースファイルからアクセスできないことを認識しているため、コードの実行内容をより正確に推測でき(「この関数はこの変数を変更しません」など)、より高速なコードを生成する場合があります。異なる変換ユニット間でこの種の最適化を行うことができるコンパイラ/リンカーはほとんどありません。

1
Adam Rosenfield