2012-02-24 16 views
20

私は.hファイルで定義されているいくつかの小さな関数を持っています。それは小さなプロジェクトです(今)。宣言と定義を別々にすることの苦痛を避けたいと思います。なぜなら、それらは常に変化するからです。多重定義シンボルを避けるために、staticまたはinlineのいずれかを指定できます。何が優先されるべきなのですか?ヘッダファイルに定義された小さな関数:インラインまたは静的?

私はヘッダーに関数を定義することは一般的に悪い習慣であることを知っています。答えに言及する必要はありませんが、この質問は技術的に意味されています。

+1

それは**それらを定義しない、ヘッダーで**それらを実装するために悪いです; Cのヘッダファイルのアイデアを) – m0skit0

+0

/C++開発者のための追加作業を作成し、私は誰もが、コードサイズが小さく宣言 – linquize

+1

を複製したいと考えていません理解しますそれともそれが小さいか:D? – UmNyobe

答えて

22

私はstatic inlineを使用しますが、staticも同様に動作します。ヘッダが複数の翻訳単位に含まれている場合は、複数の外部定義を取得したいので、

externextern inlineが出ているので、あなたはstaticstatic inlineinline仕様を検討する必要があります。

Hepticは、inlineが指定されているかどうかにかかわらず、ほとんどのコンパイラがインライン化の機能を考慮していることを正しく示しています。つまり、inlineの主な影響はリンケージへの影響です。

しかし、staticの定義には内部リンケージがあるため、staticstatic inlineの間に大きな違いはありません。ヘッダーファイルの関数定義については、static inlineを好んで使用しています(経験則:ヘッダーファイルはextern宣言、static const変数定義、static inline関数定義のみを含む必要があります)。 インライン定義、標準状態(C99 6.7.4、§6)

staticせず

inlineまたはextern結果は、翻訳者が使用することができる外部の定義に代わるものを提供します 同じ翻訳単位で関数への呼び出しを実装します。 関数への呼び出しがインライン定義または外部定義を使用するかどうかは不明です。

つまり、インライン定義には常に外部定義が付いている必要があります。これはあなたが探しているものではありません。

C99インラインセマンティクスの微妙な情報については、this answerClang homepageおよびC99 Rationale (PDF)に記載されています。

-std=c99または-std=gnu99が存在する場合、GCCはC99セマンティクスのみを使用することに注意してください。

+0

@Heptic:標準の文言はやや曖昧ですが、私が理解しているように、コンパイラは常にインライン定義を完全に無視して外部定義に完全に自由になります。そうした定義がないと明らかに失敗します別の翻訳単位で... – Christoph

+0

@Heptic:私の解釈は正しいようです - 付録の例を参照してください。C99 7.6.4§8 – Christoph

+0

@Heptic:また、すべての主要なコンパイラ/ gccは '-std = c99'や' -std = gnu99'が存在する場合、C99セマンティクスも尊重します... – Christoph

0

私は静的インラインはあなたがインラインしたい機能のために行くための方法です、そして、あなたがしたくない人のためだけ静的と思います。

静的視認性を意味するが、インラインは、標準(C99)での視認性に関する曖昧です。とにかく、それは目的ではありません:インラインは、インライン関数のためのものです。したがって、望ましくない視点から副作用があります。

+0

なぜあなたは説明を怠った。 –

+0

"inlineはあいまいで、externキーワードも許可して目的を破ります。" – m0skit0

+0

私は説明を展開しました。あなたがdownvoteのときにコメントすることができれば幸いです。) – m0skit0

3

質問はC(ないC++)程度であるので、inline

  1. あなたはを望むことを意味5(6.7.4、ISO9899-1999( "できるだけ速くなる機能を呼び出すこと" ))。同じパラグラフでは、この提案がどの程度有効であるかは実装定義であると述べています。言い換えれば、ほとんどベアリングを持たず、インライン化をまったく意味しません(実際には、インラインでないのは命令キャッシュ効果のためにかなり高速かもしれません)。
  2. extern(ISO9899-1999、6.7.4と組み合わせて、いくつかの制限や特殊なケース(6)が、例えば外部結合を持つinline funcitonは、同じコンパイル単位で定義されなければならず、インライン定義が可能ありますエラーなしで他の場所extern定義(必ずしも良いことではありません、二つの機能は、機能的に同等である必要はありませんので、コンパイラがいつでも使用する1指定されていません!)。

リンカへの影響Hepticによって与えられたものはC++には必要ですが、Cでは必須ではありません(私が知る限り)。それらは必ず" ISO14882,7.1.2(4)のすべての翻訳単位で同じアドレスを持つものとする。私はC99の似たような句を知らない。
しかし、まったく異なる言語CとC++は通常、同じC/C++コンパイラとリンカーを使用するため、Cと同じように動作する可能性があります。

あなたの質問にどう答えますか?十分だと感じたらinlineを使用してください。考えられる落とし穴はexternです。さもなければ、それを離れて置いて、それを正しくするためにコンパイラを信頼してください。

+0

この回答がどれほど有効かわかりません。あなたがそれを使用しないかもしれないことを示唆している、あなたはリンク時に複数の定義エラーを取得しないでしょうか? –

+0

@Matt Joiner:おそらくそれは依存しています。私が言っていることは、ヘッダーやソースに定義を入れるかどうかに関して、正しいことも間違いもないのと同じ意味で、「インライン」を作るための、実際には「正しい」または「間違った」というわけではありません - あなたはこれらのいずれか、あるいは両方を行うことができ、一般に間違っているものはありません。これは設計上の選択です。あなたは二重定義で問題に遭遇するかどうか(あなたの懸念については一般的に正しいです!)は別の問題です。確かにODRがあります。しかしヘッダは一度しか含まれていないかもしれません(われわれはわかりません)。もし#ifdefがあれば、もしそうでなければ... – Damon

+0

... OPが実際にヘッダに定義を入れたい場合'' gnu_inline''のように、ルールを完全に変更するコンパイラ機能(移植性が厳密に要求されない場合)があります。それはおそらく#else節でもう一つのextern宣言を必要とするでしょうが...かなりですが、ああ、うーん...結局、正しいと感じるものを一つ選択する必要があります。 – Damon

関連する問題