2012-04-20 8 views
8

Ricevo sempre un errore di compilazione quando provo a definire una funzione C nel file di intestazione appena sopra l'interfaccia della classe.Perché non posso definire semplici funzioni C nel file di intestazione?

ma quando faccio lo stesso nel file di implementazione e do una dichiarazione nell'intestazione. Le cose vanno bene.

Volevo sapere, perché è così che ho definito enum, structs, costante NSStrings nel file di intestazione, quindi perché non funzioni C?

risposta

14

Questo è il modo in cui funziona il C linker (o editor di collegamenti). Quando il compilatore C incontra una definizione di funzione, prepara il codice assemblatore che implementa quella funzione e lo contrassegna con un simbolo che dice al linker "questo è dove inizia la funzione con questo nome". Il simbolo viene in genere denominato con un trattino basso seguito dal nome della funzione, ad es. _printf.

Se si definisce la funzione in un file di intestazione, ogni file .c o .m che importa questa intestazione compilerà la funzione e farà sì che il compilatore emetta lo stesso simbolo. Il linker si aspetta di trovare solo un'istanza di ciascun simbolo, quindi si tratta di un errore.

Questo non è correlato all'esistenza delle protezioni #include o all'utilizzo di #import anziché #include. Il compilatore C funziona sulle singole unità di traduzione - con cui significa singoli file di origine. Le strategie di preprocessore impediscono di includere lo stesso file di intestazione due volte in un singolo file sorgente, ma non fanno nulla per coordinare le attività su più file. Ciò significa che è valido includere le stesse intestazioni in diversi file sorgente: significa anche che quando si compilano file diversi, possono (legittimamente) contenere lo stesso simbolo.

È compito dell'editor di collegamento riunire questi file, risolvendo qualsiasi riferimento a simboli sconosciuti in fase di compilazione. Se provi a collegare oggetti (il nome di unità di traduzione compilate e assemblate) che hanno lo stesso simbolo nello stesso archivio, libreria condivisa o eseguibile, otterrai l'errore che stai vedendo qui.

Solutions:

  • Non definire la funzione nell'intestazione, basta dichiararlo lì e definirlo in un file di implementazione; come hai già trovato funziona.
  • Definire la funzione nell'intestazione, ma includere solo quell'intestazione in un punto del codice. Questo è spesso inaccettabile per motivi di design.
  • Definire la funzione nell'intestazione con il modificatore inline. Le funzioni inline vengono semplicemente copiate dal compilatore nella funzione in cui vengono chiamate, quindi un simbolo del linker non viene mai emesso per loro. Questo ha i suoi trade-off che si may wish to read more about.
+0

shuldn't #import (anziché #include) include un file solo una volta? E .. puoi anche usare include guard (#ifndef MYFILE_H #define MYFILE_H ... #endif) – Francesco

+1

Grazie per la domanda @Francesco, ho incorporato una risposta sopra (la versione breve è che le guardie del preprocessore non si fermeranno ottieni errori di collegamento). –

+0

Ma ... stiamo parlando di definizioni o dichiarazioni di funzioni C? Perché .. Ho provato con una definizione di funzione in un file .h e includere il doppio del file. Se uso #include ottengo la "ridefinizione" della funzione. Se uso #import o guards (in ogni file .h) non ottengo errori ... – Francesco

Problemi correlati