2010-02-07 20 views
23

Le mie conoscenze di base su C e il processo di compilazione sono arrugginiti ultimamente. Stavo cercando di capire la risposta alla seguente domanda, ma non sono riuscito a collegare le basi della fase di compilazione, collegamento e pre-elaborazione. Anche una rapida ricerca su Google non ha aiutato molto. Così, ho deciso di venire in ultima fonte di conoscenza :) Definizione di variabile nei file di intestazione

lo so: Le variabili non devono essere definiti nei file .h. Va bene a dichiararli lì.

Perché: Perché un file di intestazione potrebbe avere incluso da più luoghi, ridefinendo così il più di una volta variabile (linker dà l'errore).

Possibile soluzione: Utilizzare le intestazioni nei file di intestazione e definire la variabile in questo.

È davvero una soluzione: No. Perché gli header-guard sono per la fase di pre-elaborazione. Questo per dire al compilatore che questa parte è già stata inclusa e non includerla ancora una volta. Ma il nostro errore di definizione multipla arriva nella parte linker - molto dopo la compilazione.

Questa cosa mi ha confuso su come il pre-elaborazione del collegamento & funziona. Ho pensato che la pre-elaborazione non includesse semplicemente il codice, se il simbolo dell'intestazione è stato definito. In tal caso, non dovrebbe essere risolta anche la definizione multipla di un problema variabile?

Cosa succede che queste direttive di pre-elaborazione salvino il processo di compilazione dalla ridefinizione dei simboli sotto le guardie di intestazione, ma il linker ottiene ancora più definizioni del simbolo?

risposta

24

La protezione della testata protegge da inclusioni multiple in un singolo file sorgente, non da più file sorgente. Immagino che il tuo problema derivi dal non capire questo concetto.

Non è che le protezioni del pre-processore stiano risparmiando durante il periodo di compilazione da questo problema. In realtà durante la compilazione, un solo file sorgente viene compilato in un oggetto, le definizioni dei simboli non vengono risolte. Ma, in caso di collegamento quando il linker tenta di risolvere i definitoni del simbolo, viene confuso vedendo più di una definizione che lo colloca per segnalare l'errore.

+0

yikes ... quello era in realtà semplice :) – Methos

10

Si hanno due file .c. Vengono compilati separatamente. Ognuno include il tuo file di intestazione. Una volta. Ognuno ottiene una definizione. Sono in conflitto al momento del collegamento.

La soluzione convenzionale è:

#ifdef DEFINE_SOMETHING 
int something = 0; 
#endif 

Poi si #define DEFINE_SOMETHING in un solo file .c.

+0

Una soluzione migliore è una dichiarazione nell'intestazione e una definizione in un solo file .c. –

+0

D'accordo, ma ho pensato che l'OP lo sapesse :-) – bmargulies

24

Una cosa che ho usato in passato (quando le variabili globali erano in voga):

file di var.h:

... 
#ifdef DEFINE_GLOBALS 
#define EXTERN 
#else 
#define EXTERN extern 
#endif 
EXTERN int global1; 
EXTERN int global2; 
... 

Poi in uno file .c (di solito il uno contenente main()):

#define DEFINE_GLOBALS 
#include "var.h" 

Il resto dei file di origine include solo "var.h" normalmente.

Si noti che DEFINE_GLOBALS non è un'intestazione, ma piuttosto consente di dichiarare/definire le variabili a seconda che sia definito. Questa tecnica consente una copia delle dichiarazioni/definizioni.

+0

-1: Non si risponde alla domanda attuale ... – 3lectrologos

+11

Hmm, vero. È semplicemente una buona soluzione. +1 per compensare un downvote stupido. –

+0

@Richard: FYI, nessun gioco di parole: è "in voga", non "in voga". – Multisync

8

Le protezioni di intestazione fermano un file di intestazione che viene incluso più volte nella stessa unità di traduzione (vale a dire nello stesso file sorgente .c).Non hanno alcun effetto se si include il file in due o più unità di traduzione.

+0

sì ... hai ragione. – Methos

Problemi correlati