Определение статического массива в исходный файл на C или C ++ - PullRequest
12 голосов
/ 10 января 2011

Я знаю, что это вопрос, который должен знать каждый программист, но я не знаю.Долгое время не программировал на C, и я многое забыл.

Мой вопрос:

У меня есть три огромных статических массива, определенных в заголовочном файле.Кто-то сказал мне, что гораздо лучше объявить их как 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 ++, могу ли я определить класс?

ОБНОВЛЕНИЕ: Я думаю, что проблема заключается в:Каждый исходный файл, в который включены эти заголовки (даже косвенно), будет генерировать свое собственное определение для этих статических массивов.Нет гарантии, что компилятор / компоновщик оптимизирует их в одно определение, даже в исходных файлах, где они не используются.Фактически, во многих случаях компилятор не может их оптимизировать.Это может привести к тому, что ваши статические данные будут занимать много места на диске и, возможно, также оперативную память.

Спасибо.

Ответы [ 5 ]

18 голосов
/ 10 января 2011

static и extern одновременно не имеет смысла. static в области видимости файла делает массив недоступным для других файлов, а extern сообщает компилятору, что ваш массив определен где-то еще.

Вы можете делать то, что предлагает 321008, , за исключением того, что вы не объявляете свои массивы статическими , что является недопустимым C и C ++. Это дает вам три глобальные переменные, которые вы можете использовать везде, где включен заголовочный файл.

Например, вот так:

// .h file:

extern const float TEMPLEVertices[];

// .cpp (or .c) file:

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

Или вы можете делать то, что предлагает Фортран, но это даст вам доступ только к области файла, а не к глобальным переменным.

Вы не никоим образом не должны определять класс, если используете исходный файл C ++. В отличие от Java, C ++ не принуждает вас к объектно-ориентированному проектированию (возможно, это хорошо обсуждать или нет, но в любом случае).

РЕДАКТИРОВАТЬ: Что касается обновления вашего вопроса, это потому, что вы определяете их как static. Если вам нужны только глобальные переменные, вам не следует этого делать, а вместо этого оставить одно определение (const float) и ссылаться на него с extern, как в моем примере выше.

7 голосов
/ 10 января 2011

Я однажды увидел в исходном коде Quake2 забавный трюк, который на самом деле был просто необычным способом использования include:

просто сделать:

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

и т. Д.

И сохраняйте только данные во включаемых файлах.

Вы все равно можете объявить их как extern в модуле компиляции, но это немного опровергает ситуацию.

5 голосов
/ 10 января 2011

Это очень просто, на самом деле; Я продемонстрирую на более простом примере простую примитивную константу.

В вашем проекте у вас есть два файла pi.h и pi.cpp.

Содержимое 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 голосов
/ 10 января 2011

Ваш заголовочный файл становится:

#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];
0 голосов
/ 10 января 2011


Я обычно использую простой прием.

a) В каждом файле C / CPP я определяю имя файла _C
b) В каждом файле H / HPP, который я определяю имя файла _H

than ...

Это будет ваш включаемый файл

#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)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...