web-dev-qa-db-ja.com

CまたはC ++ソースファイルへの静的配列の定義

これはすべてのプログラマーが知っておくべき問題であることは知っていますが、知りません。長い間Cプログラミングはありませんでした。多くのことを忘れてしまいました。

私の質問は:

ヘッダーファイル内に3つの巨大な静的配列が定義されています。誰かがヘッダーファイルでそれらをexternとして宣言し、単一のCまたはC++ソースファイルで定義する方がはるかに良いと私に言った。

どうやってやるの?

これが私のヘッダーファイルです:

#ifndef _TEMPLE_OBJECT_H_
#define _TEMPLE_OBJECT_H_


#define NUM_TEMPLE_OBJECT_VERTEX 10818

static const float TEMPLEVertices[NUM_TEMPLE_OBJECT_VERTEX * 3] = {...};
static const float TEMPLENormals[NUM_TEMPLE_OBJECT_VERTEX * 3] = {...};
static const float TEMPLETexCoords[NUM_TEMPLE_OBJECT_VERTEX * 3] = {...};

#endif

C++ソースファイルを使用する場合、クラスを定義する必要がありますか?

更新:
問題は次のとおりだと思います:
これらのヘッダーが含まれているすべてのソースファイルは(間接的にも)、それらの静的配列に対して独自の定義を生成します。未使用のソースファイルであっても、コンパイラ/リンカーがそれらを単一の定義に最適化する保証はありません。実際、多くの場合、コンパイラはそれらを最適化することはできません。これにより、静的データが多くのディスク領域を消費し、場合によってはランタイムメモリも消費する可能性があります。

ありがとうございました。

14
VansFannel

staticexternを同時に使用しても意味がありません。 static at fileスコープは、他のファイルから配列にアクセスできないようにしますが、externは、配列が別の場所で定義されていることをコンパイラーに通知します。

321008が提案することを行うことができます配列を静的に宣言しないことを除いてこれは、CおよびC++に不正です。これにより、ヘッダーファイルが含まれている場所ならどこでも使用できる3つのグローバル変数が得られます。

たとえば、次のようになります。

// .h file:

extern const float TEMPLEVertices[];

// .cpp (or .c) file:

const float TEMPLEVertices[] = { 1.0, 2.0, 5.6 /* or whatever*/ };

または、fortranが提案することを実行できますが、これにより、グローバル変数ではなく、ファイルスコープのアクセスのみが可能になります。

C++ソースファイルを使用する場合は、クラスを定義する必要がありますnotを実行します。 Javaとは異なり、C++はオブジェクト指向の設計を強制しません(それが良いかどうかはおそらく議論できますが、とにかく)。

編集:あなたの質問の更新に関しては、staticとして定義するためです。グローバル変数のみが必要な場合は、それを行うのではなく、単一の定義(const float)と上記の私の例のように、externで参照します。

19
Oystein

私はかつて、Quake2のソースコードで面白い "トリック"を見たことがあります。

ただ:

static const float TEMPLEVertices[NUM_TEMPLE_OBJECT_VERTEX * 3] = {
#include "TEMPLEVertices.txt"
};

等.

含まれているファイルにデータのみを保存します。

コンパイルユニットでそれらをexternとして宣言することはできますが、これにより状況が少し整然と保たれます。

7
fortran

実際にはとてもシンプルです。簡単な例である単純なプリミティブ定数を使って説明します。

プロジェクトには、pi.hpi.cppの2つのファイルがあります。

pi.hの内容は次のようになります。

#ifndef _PI_H
#define _PI_H

extern const double PI;

#endif

pi.cppの定数は次のようになります。

#include "pi.h"

const double PI = 3.1415926535;

この定数を使用する場合は、必要な場所にpi.hを含めるだけです。値は常に同じ場所から読み取られます。

配列、オブジェクト、オブジェクトの配列、STLコンテナなど、ほとんど何でも同じことができます。特に、externと宣言されているオブジェクトがconstではない場合は、この手法を使いすぎないようにしてください。 、あなたは副作用を追跡するのが本当に難しいいくつかを作成するかもしれません。しかし、定数データの場合、これはあなたが行うことです。

5
Mephane

ヘッダーファイルは次のようになります。

#ifndef _TEMPLE_OBJECT_H_
#define _TEMPLE_OBJECT_H_


#define NUM_TEMPLE_OBJECT_VERTEX 10818

extern const float TEMPLEVertices[NUM_TEMPLE_OBJECT_VERTEX * 3];
extern const float TEMPLENormals[NUM_TEMPLE_OBJECT_VERTEX * 3];
extern const float TEMPLETexCoords[NUM_TEMPLE_OBJECT_VERTEX * 3];

#endif

ソースファイルは次のようになります。

// include header
const float TEMPLEVertices[NUM_TEMPLE_OBJECT_VERTEX * 3] = {...};
const float TEMPLENormals[NUM_TEMPLE_OBJECT_VERTEX * 3] = {...};
const float TEMPLETexCoords[NUM_TEMPLE_OBJECT_VERTEX * 3] = {...};

// rest of the source

更新:配列を明示的に指定している場合は、サイズについて言及する必要はありません。それはあなたができることです:

const float TEMPLEVertices[] = {...};

または

const float TEMPLEVertices[NUM_TEMPLE_OBJECT_VERTEX * 3];
5
341008


私は通常、簡単なトリックを使用します。

a)すべてのC/CPPファイルでfilename _ Cを定義します
b)すべてのH/HPPファイルで定義filename _ H

より...

これはインクルードファイルになります

#ifndef _TEMPLE_OBJECT_H_
#define _TEMPLE_OBJECT_H_

#define NUM_TEMPLE_OBJECT_VERTEX 10818

#ifdef _TEMPLE_OBJECT_C
const float TEMPLEVertices[NUM_TEMPLE_OBJECT_VERTEX * 3] = {...} ; /* Put here your const values */
#else
extern const float TEMPLEVerticies[] ;
#endif

#endif

私が間違っていなければ、この大胆な仕事(またはそれに非常に似たもの)...:o)

0
Mr.Gate