Определение статического массива в исходном файле C или С++

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

Мой вопрос:

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

Если использовать исходный файл С++, может мне нужно определить класс?

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

Спасибо.

Ответ 1

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

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

Например, например:

// .h file:

extern const float TEMPLEVertices[];

// .cpp (or .c) file:

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

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

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

EDIT: что касается вашего обновления вопроса, это потому, что вы определяете их как static. Если вам нужны только глобальные переменные, вы не должны этого делать, но вместо этого сохраняйте одно определение (const float) и ссылайтесь на него с помощью extern, как в моем примере выше.

Ответ 2

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

просто выполните:

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

и др.

И сохраняйте только данные во входящих файлах.

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

Ответ 3

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

В вашем проекте у вас есть два файла 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, вы можете создать некоторые действительно трудно отслеживать побочные эффекты. Но для постоянных данных это вы делаете.

Ответ 4

Ваш заголовочный файл будет выглядеть следующим образом:

#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


Обычно я использую простой трюк.

a) В каждом файле C/CPP я определяю filename_C
b) В каждом файле H/HPP я определяю filename_H

чем...

Это будет ваш файл include

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