2012-01-28 26 views
6

Ho il seguente "costanti" intestazione:Collegamento edizione con "la definizione multiplo di" errore di compilazione

/* constants.h */ 

#ifdef __cplusplus 
extern "C" { 
#endif 

#pragma once 

#ifndef CONSTANTS_H 
#define CONSTANTS_H 

const char * kFoo = "foo"; 
const char * kBar = "bar"; 

#endif 

#ifdef __cplusplus 
} 
#endif 

Sono #include -ing questa intestazione nel file X.c e Y.c.

Nota che sono non incluso questo in X.h o Y.h.

I file X.c e Y.c vengono compilati in file oggetto archiviati in una libreria statica denominata libXY.a.

Quando includo X.h e Y.h in Z.h, e quando mi collego a libXY.a, non riesco a compilare Z.c senza errori:

/* Z.h */ 

#include "X.h" 
#include "Y.h" 

io ottenere i seguenti errori di compilazione quando si tenta di compilare Z.c:

/path/to/libXY.a(X.o):(.data+0x0): multiple definition of `kFoo` 
/path/to/libXY.a(Y.o):(.data+0x0): first defined here 
/path/to/libXY.a(X.o):(.data+0x8): multiple definition of `kBar` 
/path/to/libXY.a(Y.o):(.data+0x8): first defined here 

Ho provato a impostare kFoo e kBar a extern, ma questo non aiuta

Come risolvere più definizioni, quando includo le costanti solo una volta (tramite la protezione dell'intestazione #ifndef CONSTANTS_H)?

+0

Forse non è il problema immediato (non sono sicuro), ma è necessario rimuovere il falso '#pragma once' e metti le tue guardie multiple-inclusive nella tua intestazione. Il formato standard è '#ifndef MYHEADER_H #define MYHEADER_H .... # endif' –

risposta

9

Come potrei risolvere multipla definizioni, quando includo solo le costanti una volta (tramite la protezione dell'intestazione #ifndef CONSTANTS_H)?

Con questo in constants.h:

const char * kFoo = "foo"; 

una definizione per kFoo sarà emesso in ogni traduzione che #include s constants.h. Quindi, più definizioni, che quindi si traducono in errori di collegamento.

Come osservato asaelr (+1), si dovrebbe risolvere in questo modo:

constants.h

extern const char* const kFoo; 

costanti.c

const char* const kFoo = "foo"; 

(notare che ho anche fatto il const puntatore, che è solito ciò che si vuole fare in questo caso)

+4

Ci sono alcune altre opzioni che potrebbero essere considerate. Nel contesto attuale, ciò che hai suggerito è giusto, ma: (A) 'static const char * kFoo =" foo ";' funzionerebbe senza un file constants.c separato; e (B) 'static const char kFoo [] =" foo ";' potrebbe essere una resa più accurata di ciò che è richiesto (e 4 o 8 byte meno spazio usato, a seconda dei puntatori a 32 bit contro 64 bit); e (C) 'extern const char kFoo [];' più constants.c contenente 'const char kFoo [] =" pippo ";' potrebbe essere una variazione appropriata della soluzione. Il codice probabilmente non dovrebbe essere autorizzato a fare 'kFoo =" pqr ";'. –

+0

@JonathanLeffler +1 In realtà ho iniziato a scrivere sulle varianti che potrebbero essere apportate in questo scenario in una modifica di follow-up, ma ho scartato le mie modifiche come già fatto da me e altri in questo sito. Penso che "extern const char * const kFoo;" sia in genere il modo più chiaro (usando C) per dichiarare/documentare che si tratta di una costante di stringa. Certo, questo è soggettivo. A + B) funzionerebbe, ma potrebbe risultare in un numero di canali binari. il prefisso constants.h + 'k' suggerisce che questo è un progetto osx o ios (spesso finisce nel pch). 'extern' è in genere la più semplice per la compilazione e il collegamento in tale scenario. – justin

+0

A meno che non sia effettivamente necessario un puntatore e anche la stringa, utilizzare la notazione dell'array in preferenza alla notazione del puntatore. Sono d'accordo sul fatto che le versioni statiche possono portare a gonfiare il codice e non sono generalmente raccomandate. (Le versioni puntatore portano anche al codice in aumento, aumentando l'eseguibile della dimensione di un puntatore per costante.) –

4

Non si devono definire variabili nel file di intestazione. definirli in uno dei file sorgente e dichiararli (extern) nel file di intestazione.

(Hai scritto: "Ho provato a fissare kFoo e kbar per esterno, ma questo non aiuta." Immagino che tu non li hai definito in un file di origine)

+0

Se definisco le variabili in' constants.c', ottengo "errori di riferimento non definiti a' kFoo' "durante la compilazione della libreria. (Sto compilando 'constants.c' su' constants.o' e lo includo con la libreria.) Qualche idea? –

+0

Lo hai definito o dichiarato? Come lo si collega? – asaelr

Problemi correlati