5

すべてのコードが*.c/*.hファイルのペアで編成されているCプロジェクトがあり、1つのファイルで定数値を定義する必要がありますが、他のファイルでも使用されます。この値をどのように宣言して定義する必要がありますか?

static const ...それはファイルのようにすべき*.hですか?ファイルのようextern const ...に、*.hファイルで定義されてい*.cますか?int値がプリミティブデータ型( 、、doubleなど)ではなく、achar *またはaであるかどうかは、どのように重要structですか?(私の場合はですがdouble。)

ファイル内のものを定義すること*.hは、一般的には良い考えとは思えません。ファイルで物事を宣言する必要があり*.hますが、ファイルでそれらを定義し*.cます。ただし、extern const ...コンパイラは値をインライン化できないため、このアプローチは非効率的であるように見えます。代わりに、常にそのアドレスを介してアクセスする必要があります。

この質問の本質は次のとおりです。複数の場所で値を使用するには、Cのファイルでstatic const ...値を定義する必要がありますか?*.h

4

9 に答える 9

8

私が従う規則は、H ファイルでのみ宣言し、C ファイルで定義することです。そのファイルでのみ使用されると仮定すると、単一の C ファイルで宣言および定義できます。

宣言とは、コンパイラーにその存在を通知することを意味しますが、スペースを割り当てません。これには#definetypedefextern int xなどが含まれます。

定義は、値を宣言に割り当て、それらにスペースを割り当てます ( や などint x) const int x。これには関数定義が含まれます。これらをヘッダー ファイルに含めると、コード スペースが無駄になることがよくあります。

あまりにも多くのジュニア プログラマーが、ヘッダー ファイルを挿入するときに混乱し、2 回以上定義されているconst int x = 7;ためにリンク エラーが発生するのはなぜだろうと考えているのを見てきました。x最低限、static const int xこの問題を回避するために必要だと思います。

コードの速度についてはあまり心配しません。コンピュータの (速度とコストの点での) 主な問題は、ずっと前に実行速度から開発の容易さに移行しました。

于 2008-12-10T06:46:18.853 に答える
3

定数 (実際のコンパイル時定数) が必要な場合は、3 つの方法でヘッダー ファイルに入れることができます (それで問題はありません)。

enum {
    FOO_SIZE = 1234,
    BAR_SIZE = 5678
};

#define FOO_SIZE 1234
#define BAR_SIZE 5678

static const int FOO_SIZE = 1234;
static const int BAR_SIZE = 5678;

C++ では、名前空間にスコープを設定できるため、enum の方法を使用する傾向があります。Cの場合、マクロを使用します。ただし、これは基本的に好みの問題になります。浮動小数点定数が必要な場合は、列挙型を使用できなくなりました。C++ では、最後の方法である static const double を使用します (その場合、C++ static では冗長になることに注意してください。const であるため、自動的に static になります)。Cでは、マクロを使い続けます。

3 番目の方法を使用すると、何らかの形でプログラムが遅くなるというのは神話です。取得する値は右辺値であるため、列挙型を好むだけです。アドレスを取得することはできません。これは、追加の安全性と見なされます。さらに、定型コードの記述も大幅に少なくなります。目は定数に集中しています。

于 2008-12-10T23:14:50.980 に答える
1

インラインの利点について本当に心配する必要がありますか? 埋め込みコードを書いているのでない限り、読みやすさに固執してください。それが本当に何かのマジック ナンバーである場合は、define を使用します。const バージョン文字列や関数呼び出し引数の変更などには const の方が適していると思います。そうは言っても、.c で定義し、.h で宣言する規則は、間違いなくかなり普遍的に受け入れられている規則であり、メモリ ルックアップを保存する可能性があるという理由だけでそれを破ることはありません。

于 2008-12-10T07:28:10.953 に答える
1

原則としてstatic、ヘッダーのように定義することはありません。ヘッダーで変数を定義する場合static、ヘッダーを使用する各ファイルは、宣言されているものの独自のプライベート コピーを取得します。これは、 DRY原則staticのアンチテーゼです:自分自身を繰り返さないでください

したがって、代替手段を使用する必要があります。整数型の場合、enum (ヘッダーで定義) を使用すると非常に強力です。デバッガーでもうまく機能します (ただし、より優れたデバッガーは#defineマクロ値にも役立つ場合があります)。非整数型の場合、通常は、ヘッダー内のextern宣言 (オプションで で修飾const) と 1 つの C ファイル内の単一の定義が最適な方法です。

于 2008-12-10T07:53:24.617 に答える
0

あなたの質問の本質に答えるために:
あなたは一般的にヘッダーファイルで静的変数を定義したくありません。
これにより、ヘッダーを含む各変換ユニット(Cファイル)に重複した変数が作成されます。

ヘッダー内の変数は、暗黙の可視性であるため、実際にはexternとして宣言する必要があります。良い説明については、この質問を参照してください。

実際には、コンパイラがconst型をリテラル値に変換する可能性があるため、状況はそれほど悲惨ではない可能性があります。ただし、特に最適化がオフになっている場合は、その動作に依存したくない場合があります。

于 2008-12-10T12:36:36.977 に答える
0

autoconf 環境の場合: configure ファイルでも常に定数を定義できます。AC_DEFINE() は、ビルド全体で定義するマクロだと思います。

于 2008-12-10T08:26:59.807 に答える
0

間接的にお答えします。C++ では (C とは対照的に) は をconst意味しstaticます。つまり、C++ ではstatic constと同じですconst。つまり、C++ 標準化団体がこの問題についてどのように感じているかがわかります。つまり、すべてconstの s は static でなければなりません。

于 2008-12-10T06:26:14.823 に答える
0

あなたの質問の文脈をもっと知りたいです。値の型は重要ですが、省略しています。C における const キーワードの意味は非常に微妙です。たとえば、const char *p; ポインター p が定数であることを意味するものではありません。p は好きなように書くことができます。書き込むことができないのは、p が指すメモリです。これは、p の値が変化しても当てはまります。これは、私が本当に理解している唯一のケースです。一般に、const の微妙な配置の意味がわかりません。しかし、この特殊なケースは、引数が指すメモリが変更されないという約束を関数から抽出するため、関数パラメーターには非常に役立ちます。

誰もが知っておくべきもう 1 つの特別なケースがあります: 整数です。ほとんどの場合、定数の名前付き整数は、列挙リテラルとして .h ファイルで定義する必要があります。列挙型を使用すると、関連する定数を自然な方法でグループ化できるだけでなく、これらの定数の名前をデバッガーで表示できるようになります。これは大きな利点です。

私は何万行もの C を書きました。私がそれを追跡しようとすると、おそらく数百になります。(wc ~/src/c/*.c では 85,000 と表示されていますが、その一部は生成されており、もちろん、他の場所に多くの C コードが潜んでいます)。についての 2 つのケースを除けば、const の用途はあまり見つかりませんでした。新しい有用な例を学べることを嬉しく思います。

于 2008-12-10T06:29:07.483 に答える
0

C++ では、常に使用する必要があります。

const int SOME_CONST = 17;

定数および決して

#define SOME_CONST 17

定義はほとんどの場合戻ってきて、後で噛み付きます。const は言語に含まれており、強く型付けされているため、隠れた相互作用が原因で奇妙なエラーが発生することはありません。const を適切なヘッダー ファイルに入れます。#pragma once (または #ifndef x / #define x / #endif) である限り、コンパイル エラーは発生しません。

バニラ C では、#defines を使用しなければならない場所で互換性の問題が発生する可能性があります。

于 2008-12-11T00:40:16.080 に答える