IMOは両方とも、関数が翻訳単位のみのスコープを持つようにします。
「静的」機能と「静的インライン」機能の違いは何ですか?
.c
ファイルではなく、ヘッダーファイルにinline
を配置する必要があるのはなぜですか?
inline
は、実際の呼び出しを実行する代わりに、呼び出しコードに関数の内容を埋め込む試行をコンパイラーに指示します。
頻繁に呼び出される小さな関数の場合、パフォーマンスに大きな違いが生じる可能性があります。
ただし、これは単なる「ヒント」であり、コンパイラはそれを無視する可能性があり、ほとんどのコンパイラは、可能な場合、最適化の一部としてキーワードが使用されていない場合でも「インライン」を試みます。
例えば:
static int Inc(int i) {return i+1};
.... // some code
int i;
.... // some more code
for (i=0; i<999999; i = Inc(i)) {/*do something here*/};
このタイトなループは、各反復で関数呼び出しを実行します。実際、関数の内容は、呼び出しを実行するためにコンパイラが配置する必要があるコードよりも大幅に少なくなります。 inline
は本質的に、上記のコードを同等のものに変換するようコンパイラーに指示します。
int i;
....
for (i=0; i<999999; i = i+1) { /* do something here */};
実際の関数呼び出しをスキップして戻る
明らかに、これはポイントを示すための例であり、実際のコードではありません。
static
はスコープを指します。 Cでは、関数/変数は同じ変換単位内でのみ使用できることを意味します。
デフォルトでは、インライン定義は現在の翻訳単位でのみ有効です。
ストレージクラスがextern
の場合、識別子には外部リンケージがあり、インライン定義も外部定義を提供します。
ストレージクラスがstatic
の場合、識別子には内部リンケージがあり、インライン定義は他の翻訳単位では見えません。
ストレージクラスが指定されていない場合、インライン定義は現在の翻訳単位でのみ表示されますが、識別子にはまだ外部リンケージがあり、外部定義は別の翻訳単位で提供する必要があります。コンパイラーは、関数が現在の変換単位内で呼び出される場合、インライン定義または外部定義を自由に使用できます。
コンパイラーは、定義が現在の翻訳単位で表示される関数を自由にインライン化できます(インライン化できません)(また、リンク時最適化のおかげで、異なる翻訳単位でも、C標準では実際には考慮されません)それ)、ほとんどの実用的な目的のために、static
とstatic inline
関数の定義に違いはありません。
inline
指定子(register
ストレージクラスなど)は単なるコンパイラヒントであり、コンパイラはそれを完全に無視できます。標準に準拠した非最適化コンパイラは副作用を尊重するだけでよく、最適化コンパイラは明示的なヒントの有無にかかわらずこれらの最適化を行います。
inline
とregister
は、プログラマが最適化を不可能にするコードを記述するときにコンパイラにエラーをスローするよう指示するため、役に立たないわけではありません。外部inline
定義は識別子を参照できません内部リンケージ(これらは別の翻訳単位では使用できないため)または静的ストレージ期間で変更可能なローカル変数を定義するため(これらは翻訳単位間で状態を共有しないため)、register
のアドレスを取ることはできません修飾された変数。
個人的には、ヘッダー内のstatic
関数定義もinline
とマークする規則を使用します。ヘッダーファイルに関数定義を置く主な理由は、それらをインライン化できないようにするためです。
一般に、ヘッダー内のextern
宣言に加えて、static inline
関数とstatic const
オブジェクト定義のみを使用します。
inline
とは異なるストレージクラスを持つstatic
関数を書いたことはありません。
GCCでの経験から、static
とstatic inline
は、コンパイラが未使用の関数に関する警告を発行する方法が異なることを知っています。より正確にstatic
関数を宣言し、現在の翻訳単位で使用されていない場合、コンパイラは未使用の関数に関する警告を生成しますが、static inline
に変更することで警告を禁止できます。
したがって、私はstatic
が翻訳単位で使用されるべきであると考えがちであり、余分なチェックコンパイラが未使用の関数を見つけるのに役立ちます。また、static inline
をヘッダーファイルで使用して、警告を発行せずに(外部リンクがないため)インライン化できる関数を提供する必要があります。
残念ながら、私はその論理の証拠を見つけることができません。 GCCのドキュメントからでも、inline
は未使用の関数警告を禁止すると結論付けることはできませんでした。誰かがその説明へのリンクを共有してくれたら幸いです。
Cでは、static
は、定義する関数または変数がこのファイルでのみ使用できることを意味します(つまり、コンパイル単位)
したがって、static inline
は、このファイルでのみ使用できるインライン関数を意味します。
編集:
コンパイル単位は翻訳単位
言語レベルではなく、一般的な実装レベルにある1つの違い:gccの特定のバージョンは、参照されないstatic inline
関数をデフォルトで出力から削除しますが、参照されない場合でもプレーンstatic
関数を保持します。これがどのバージョンに当てはまるかはわかりませんが、実用的な観点からは、ヘッダーのinline
関数に常にstatic
を使用することをお勧めします。