web-dev-qa-db-ja.com

Cプログラミングで静的構造を使用する理由とタイミング

変更するように求められたドライバーコードで静的構造体宣言が頻繁に見られました。

structsが静的と宣言されている理由とそうする動機に関する情報を探してみました。

あなたの誰かがこれを理解するのを助けてくれますか?

37
kutty

Cのstaticキーワードには、適用されるコンテキストに応じていくつかの効果があります。

  • 関数内で宣言された変数に適用されると、その変数の値は関数呼び出し間で保持されます。
  • 関数の外で宣言された変数、または関数に適用された場合、その変数または関数の可視性は "translation unit" で宣言されている-つまりファイル自体に制限されます。変数の場合、これは一種の「ローカルに見えるグローバル変数」に要約されます。

両方の使用法は、ドライバーのような比較的低レベルのコードではかなり一般的です。

前者、および変数に適用される後者は、関数が呼び出し間で状態の概念を保持することを可能にしますが、これは非常に便利ですが、これは、コードがそれが存在するコンテキストで使用されているときにあらゆる種類の厄介な問題を引き起こす可能性があります複数のスレッドまたは複数の呼び出し元により、同時に使用されています。 1人の「ユーザー」によってコードが厳密に順番に呼び出されることを保証できない場合は、呼び出しごとに呼び出し側によって維持されている一種の「コンテキスト」構造を渡すことができます。

関数に適用される後者は、プログラマーがモジュールの外部から関数を不可視にすることを可能にし、それは[〜#〜] may [〜#〜]特定のアーキテクチャのコンパイラでは、変数/関数をモジュールの外部で使用可能にする必要がないことをコンパイラが認識しているため、たとえば、関数をインライン化できるため、多少高速になります。

32
fvu

明らかに他のすべての答えが見逃しているように見えるもの:staticは、オブジェクトのstorage durationであり、automatic(local variables)および- allocated(mallocおよびフレンドによって返されるメモリ)。

静的ストレージ期間を持つオブジェクトは、指定されたイニシャライザーを使用してmain()が開始する前に初期化されます。指定されていない場合は0が割り当てられたように初期化されます(構造体と配列の場合、これは各メンバーに再帰的に適用されます)。

識別子に設定する2番目のプロパティstaticは、そのlinkageです。これはリンク時に使用される概念で、どの識別子が同じオブジェクトを参照するかをリンカーに伝えます。 staticキーワードは、識別子に内部リンケージを持たせます。これは、別の翻訳単位で同じ名前の識別子を参照できないことを意味します。

そして、私が前に読んだすべてのずさんな答えについて知識を深めるために:静的変数は宣言されたファイルのどこでも参照することはできません。そのスコープは、その宣言(関数定義の間にある場合もあります)からソースファイルの終わりまで(またはさらに小さい場合は、囲みブロックの終わりまで)です。

30
Jens

structvariable

static struct S s;のようなstructvariableの場合、これは広く議論されています: Cの「静的」とは?

structdefinition:効果なし

static struct S { int i; int j; };

以下とまったく同じです。

struct S { int i; int j; };

絶対に使用しないでください。 GCC 4.8を実行すると、警告が表示されます。

これは、構造体定義にストレージがなく、変数や関数などのオブジェクトファイルにシンボルを生成しないためです。コンパイルと逆コンパイルを試してください:

struct S { int i; int j; };
int i;

で:

gcc -c main.c
nm main.o

Sシンボルはありませんが、iシンボルはあります。

コンパイラは、定義を使用して、コンパイル時にフィールドのオフセットを計算します。

これは通常、ヘッダーに含まれる構造体定義です。複数回含まれていても、複数の個別のデータは生成されません。

enumについても同様です。

C++ structdefinition:C++ 11で非推奨

C++ 11 N3337標準ドラフト 付録C 7.1.1:

変更:C++では、静的または外部指定子はオブジェクトまたは関数の名前にのみ適用できます。これらの指定子を型宣言で使用することは、C++では無効です。 Cでは、これらの指定子は型宣言で使用されると無視されます。

参照: https://stackoverflow.com/a/31201984/895245

変数をstaticとして宣言すると、その変数は translation unit (グローバルに宣言されている場合)でのみ表示されるか、呼び出しから呼び出しまでその値を保持します(関数内で宣言されている場合)。

あなたの場合、最初のケースだと思います。その場合、おそらくプログラマーは構造を他のファイルから見えるようにしたくなかったでしょう。

8
Mihai Maruseac

staticstruct修飾子は、構造の可視範囲を現在の翻訳単位(つまりファイル)に制限します。

注:この回答は、(他のレスポンダーが示したように)宣言が関数内にないことを前提としています。

7