Cで、ファイル内の変数のスコープ制限としてstatic
キーワードを使用することについて疑問に思います。
私が見ているようにCプログラムを構築する標準的な方法は次のとおりです。
static
で制限されている可能性があります。とにかく変数がhファイルで公開されていない場合、gobalをstatic
として宣言する2つの理由がわかります。
extern
として再宣言しないようにすることです。リンカは、変数がextern
とstatic
の両方であることを嫌うと思います。 (他の誰かが所有する変数をextern
として再宣言するファイルのアイデアは嫌いですが、それは大丈夫ですか?)他の理由はありますか?
static
関数についても同じことが言えます。プロトタイプがhファイルで公開されていない場合、他のファイルはとにかく関数を使用しない可能性があるので、なぜそれをstatic
と定義するのですか?同じ2つの理由がわかりますが、それ以上はわかりません。
他のリーダーへの通知について話すときは、コンパイラー自体をリーダーと見なしてください。変数がstatic
と宣言されている場合、最適化が開始される程度に影響を与える可能性があります。
static
変数をextern
として再定義することは不可能ですが、コンパイラーは(いつものように)自分をぶら下げるのに十分なロープを提供します。
あるファイルにstatic int foo;
を書き込み、別のファイルにint foo;
を書き込むと、これらは異なる変数と見なされます同じ名前とタイプであるにもかかわらず、コンパイラは文句を言いませんが、おそらく後でコードを読み取ったりデバッグしたりしようとすると、非常に混乱します。 (2番目のケースでextern int foo;
と書くと、他の場所で非静的int foo;
を宣言しない限り、リンクに失敗します。)
グローバル変数がヘッダーファイルに表示されることはめったにありませんが、表示される場合はextern
と宣言する必要があります。そうでない場合、コンパイラによっては、そのヘッダーを含むすべてのソースファイルが変数の独自のコピーを宣言するリスクがあります。これにより、リンク障害(多重定義シンボル)が発生し、最悪の場合、いくつかの紛らわしいシャドウイングが発生します。
ファイルレベルで変数static
を宣言することにより(関数内のstatic
は異なる意味を持ちます)、他のユニットがそれにアクセスすることを禁止します。別のユニット(extern
で宣言)内で変数を使用しようとすると、リンカーはこのシンボルを見つけられません。
static関数を宣言すると、関数の呼び出しは「ニアコール」であり、理論的には「ファーコール」よりもパフォーマンスが向上します。あなたはより多くの情報のためにグーグルすることができます。 これ は私が簡単なグーグル検索で見つけたものです。
ファイルacで変数fooを静的にせずに宣言し、ファイルbcで変数fooを静的にせずに宣言すると、両方が自動的にexternになります。つまり、両方を初期化するとリンカーが文句を言い、そうでない場合は同じメモリ位置を割り当てる可能性があります。文句はありません。コードのデバッグを楽しんでください。
静的にせずにファイルacに関数foo()を記述し、静的にせずにファイルbcに関数foo()を書き込むと、リンカーは文句を言うかもしれませんが、そうでない場合、foo()へのすべての呼び出しは同じ機能。コードのデバッグを楽しんでください。
グローバル変数が静的であると宣言されている場合、コンパイラーは、そうでない場合よりも優れた最適化を行うことができる場合があります。コンパイラは、変数が他のソースファイルからアクセスできないことを認識しているため、コードの実行内容をより正確に推測でき(「この関数はこの変数を変更しません」など)、より高速なコードを生成する場合があります。異なる変換ユニット間でこの種の最適化を行うことができるコンパイラ/リンカーはほとんどありません。