2011-01-10 24 views
10

Sé que esta es una pregunta que todo programador debe saber, pero no sé. Mucho tiempo sin programación C y he olvidado muchas cosas.Definición de una matriz estática en un archivo fuente C o C++

Mi pregunta es:

tengo tres enormes arreglos estáticos definidos dentro de un archivo de cabecera. Alguien me dijo que es mucho mejor declararlos como extern en el archivo de encabezado y definirlos en un solo archivo de origen C o C++.

¿Cómo puedo hacer eso?

Aquí está mi archivo de cabecera:

#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 

Si un uso un fichero fuente C++, podría necesitar para definir una clase?

ACTUALIZACIÓN:
Creo que el problema es:
Cada archivo de origen en el que los encabezados se incluyen (aunque sea indirectamente) generará su propia definición de los arreglos estáticos. No hay garantía de que el compilador/vinculador los optimice en una única definición, incluso en los archivos fuente donde no se utilizan. De hecho, en muchos casos el compilador no puede optimizarlos. Esto podría provocar que sus datos estáticos consuman una gran cantidad de espacio en disco, y posiblemente también memoria de tiempo de ejecución.

Gracias.

+0

Shoud no debe ser el caso de GCC y optimice la compilación habilitada. Aquí hay información sobre "-fkeep-static-consts" del [https://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html]https://gcc.gnu.org/onlinedocs/gcc/Optimize -Options.html "Emitir variables declaradas estáticas const cuando la optimización no está activada, incluso si las variables no están referenciadas. GCC habilita esta opción de forma predeterminada. Si desea forzar al compilador a verificar si se hace referencia a una variable , independientemente de si la optimización está activada o no, use la opción -fno-keep-static-consts." – Andy

Respuesta

16

static y en extern al mismo tiempo no tiene sentido. static en el alcance del archivo hace que la matriz sea inaccesible para otros archivos, mientras que extern le dice al compilador que su matriz está definida en otro lugar.

Puede hacer lo que sugiere08, excepto que no declara que las matrices están estáticas que son C y C++ ilegales. Eso le da tres variables globales que puede usar dondequiera que se incluya el archivo de encabezado.

Por ejemplo así:

// .h file: 

extern const float TEMPLEVertices[]; 

// .cpp (or .c) file: 

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

O bien, puede hacer lo que sugiere FORTRAN, pero que le dará acceso a los archivos, sólo alcance, variables globales no.

Hace no de ninguna manera tiene que definir una clase si utiliza un archivo fuente C++. A diferencia de Java, C++ no te obliga a un diseño orientado a objetos (si eso es bueno o no, probablemente pueda discutirse, pero de todos modos).

EDITAR: En cuanto a su actualización de pregunta, es porque los define como static. Si solo desea variables globales, no debe hacer eso, sino mantener una sola definición (const float) y hacer referencia a ella con extern, como lo indica mi ejemplo anterior.

+0

Se compila, pero el vinculador arroja un error: 'referencia indefinida a' TEMPLEVertices'' y lo mismo para las otras dos matrices. – VansFannel

+0

+1 por mencionar que "de ninguna manera tiene que definir una clase en un archivo fuente C++". – BeeBand

+0

@VansFannel: ¿Y cuál es tu código? ¿Podría actualizar su pregunta con esto, tal vez? Tenga en cuenta que debe incluir el archivo .h donde quiera usar la matriz. – Oystein

5

Una vez vi en el código fuente Quake2 un "truco" divertido, que en realidad era sólo una forma inusual de utilizar un include:

acaba de hacer:

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

etc.

Y mantenga solo los datos en los archivos incluidos.

Aún puede declararlos como extern en la unidad de compilación, pero esto mantiene las cosas un poco más ordenadas.

+0

Gracias por su respuesta, pero creo que tendré el mismo problema. He actualizado mi pregunta con más detalles sobre el problema. – VansFannel

3

Su archivo de cabecera se convierte en:

#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 

Mientras que el archivo de origen se convierte en:

// 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 

Actualización: Si está especificando las matrices de manera explícita, que no tiene que mencionar los tamaños. Es decir que puede hacer:

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

o

const float TEMPLEVertices[NUM_TEMPLE_OBJECT_VERTEX * 3]; 
+0

Eso no es legal C o C++. – Oystein

+0

¿Eso es legal C o C++? – VansFannel

+0

Así es como usted hazlo! @ Øystein: ¿Qué crees que está mal con él? –

0


por lo general utilizan un truco sencillo.

a) en cada archivo de C/CPP defino nombre de archivo _C
b) En cada archivo H/HPP defino nombre de archivo _H

que ...

esto va a ser su archivo de inclusión

#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 

Si no me equivoco este Shaud funciona (o algo muy similar a la que) ...: o)

+0

Quiero poner definiciones de matriz dentro de un archivo fuente C o C++. – VansFannel

5

Es muy simple, en realidad; Demostraré con un ejemplo más fácil, una simple constante primitiva.

En su proyecto, tiene dos archivos pi.h y pi.cpp.

El contenido de pi.h se parece a esto:

#ifndef _PI_H 
#define _PI_H 

extern const double PI; 

#endif 

Los contants de pi.cpp se ve así:

#include "pi.h" 

const double PI = 3.1415926535; 

Si desea utilizar esta constante, que sólo incluyen pi.h donde es necesario. El valor siempre se leerá desde la misma ubicación.

El mismo se puede hacer con casi cualquier cosa - matrices, objetos, matrices de objetos, contenedores STL, etc Sólo asegúrese de no uso excesivo de esta técnica - especialmente cuando los objetos declarados extern no son const, puede crear algunos realmente difícil de rastrear los efectos secundarios. Pero para datos constantes, esto es lo que haces.

Cuestiones relacionadas