2009-07-22 8 views

Respuesta

89

Usted debe declarar la variable en un archivo de cabecera:

extern int x; 

y luego define en uno C archivo:

int x; 

En C, la diferencia entre una definición y una declaración es que la definición reserva espacio para la variable, mientras que la declaración simplemente introduce la variable en la tabla de símbolos (y hará que el enlazador vaya a buscarla cuando se presente). para vincular el tiempo).

+3

** ¡Ambos ** son declaraciones! En el alcance del archivo, el segundo no es una definición (completa), sino una _preparativa _. – Olaf

29

Puede (debería) declararlo como extern en un archivo de encabezado y definirlo exactamente en el archivo .c.

Tenga en cuenta que ese archivo .c también debe utilizar la cabecera y que el patrón estándar se parece a:

// file.h 
extern int x; // declaration 

// file.c 
#include "file.h" 
int x = 1; // definition and re-declaration 
+0

De hecho, * debería * siempre usar el encabezado, de modo que si los tipos se salen de control entre la declaración y la definición el compilador le dirá. – caf

+0

gato, tienes razón, voy a volver a decirlo un poco. –

9

Si se declara como

int x; 

en un archivo de cabecera que a su vez se incluye en varios lugares, que va a terminar con varias instancias de x (y potencialmente de compilación o problemas de enlace).

La forma correcta de abordar esto es tener el archivo de cabecera decir

extern int x; /* declared in foo.c */ 

y luego en foo.c se puede decir

int x; /* exported in foo.h */ 

A continuación, puede incluir el archivo de cabecera en el mayor número lugares como quieras

3

La clave es mantener las declaraciones de la variable en el archivo de encabezado y el archivo de origen de la misma.

Yo uso este truco

------sample.c------ 
#define sample_c 
#include sample.h 

(rest of sample .c) 

------sample.h------ 
#ifdef sample_c 
#define EXTERN 
#else 
#define EXTERN extern 
#endif 

EXTERN int x; 

Ejemplo.c solamente se compila una vez y que define las variables. Cualquier archivo que incluye sample.h solo tiene el "extern" de la variable; sí asigna espacio para esa variable.

Cuando cambie el tipo de x, cambiará para todos. No tendrá que recordar cambiarlo en el archivo de origen y el archivo de encabezado.

+2

¿Cómo lidiar con la inicialización? - extern int x = 6; daría una advertencia en la mayoría de los compiladores. – Dipstick

+0

@chrisharris: eso es una limitación. Normalmente tengo un Init() en cada módulo para inicializar las variables. – Robert

+0

¿No le parece menos engorroso tener una declaración externa en el encabezado y definición en el archivo C? Como @caf comentó, si los tipos no coinciden, obtienes una advertencia (siempre incluyo el archivo de encabezado en el archivo c correspondiente, ya que requiero que todas las funciones tengan un prototipo). – Gauthier

0

¿Qué tal esta solución?

#ifndef VERSION_H 
#define VERSION_H 

static const char SVER[] = "14.2.1"; 
static const char AVER[] = "1.1.0.0"; 

#else 

extern static const char SVER[]; 
extern static const char AVER[]; 

#endif /*VERSION_H */ 

El único inconveniente que veo es que el guardia incluir no te salva si se incluyen dos veces en el mismo archivo.

+1

1) El protector #ifndef evita múltiples definiciones en un * archivo * fuente * (por lo tanto, las definiciones externas no hacen nada). 2) Declarar una variable estática en un encabezado significa que cada archivo fuente que lo incluye tendrá su propia versión de esa variable en lugar de una única variable compartida. Técnicamente, esto se vinculará, pero el comportamiento puede no ser deseado (puede que no se noten ya que usaste variables de const en este ejemplo, pero úsalo para algo no const y verás que importa). La respuesta aceptada es casi siempre la solución adecuada. – Assimilater

Cuestiones relacionadas