2013-08-25 13 views
8

Quindi sto seguendo in Head First C e siamo in un capitolo in cui impariamo a compilare più file insieme. Uno di questi è encrypt.c.perché devo includere un file di intestazione .h nel file .c con lo stesso nome?

#include "encrypt.h" 


void encrypt(char *message) 
{ 
    char c; 
    while (*message) { 
    *message = *message^31; 
    message++; 
    } 
} 

Il file encrypt.h ripete la prima linea con un punto e virgola alla fine, perché ne ho bisogno? Capisco perché avrei bisogno dei file di intestazione per risolvere il problema dell'utilizzo di una funzione prima che sia definita, quindi potrei capire #incluso in un file che utilizza encrypt.c, ma perché dovrei averne bisogno all'interno di encrypt.c? E 'solo una di quelle ragioni "perché"?

+0

Non è possibile utilizzare una funzione prima che sia definita. È possibile dichiarare l'intestazione per la funzione e quindi utilizzarla dopo che è stata definita. Ma un file di intestazione non ti garantisce il superutente in quanto ti permette di usare una funzione non dichiarata. – smac89

+3

Non rilevante in questo particolare esempio, ma i file di intestazione spesso definiscono anche 'typedef's e' struct's e tutti i tipi di cose che le funzioni dichiarate in quell'intestazione potrebbero voler usare. –

+0

Ne ho anche altri. Questo libro ha difetti ma lo fanno tutti. – punstress

risposta

16

Se i contenuti di encrypt.c vengono visualizzati nella loro interezza, non è necessario l'intestazione. Ma è comunque una buona idea includerlo perché:

  1. Se una funzione nel file utilizza un altro, l'ordine di definizione è importante perché il destinatario deve essere definito prima del chiamante. È anche possibile avere due funzioni A e B in cui ciascuna chiama l'altra, nel qual caso non è possibile ottenere il codice da compilare senza almeno una dichiarazione in avanti. Includere l'intestazione con le dichiarazioni avanzate risolve questi problemi.
  2. Consumare l'intestazione proprio come fa il codice client è un buon modo per fare in modo che il compilatore evidenzi le discrepanze tra le firme nelle dichiarazioni di inoltro e le definizioni di funzione effettive. Se non rilevato, questo tipo di problema può portare a un comportamento "interessante" in fase di esecuzione e a un sacco di strappi.
+1

Mi piace il tuo secondo punto. Il libro ha sollevato il tuo primo punto di funzioni che si chiamano reciprocamente, quindi ping le chiamate ping pong e ping ping, e capisco come l'intestazione possa risolverlo, ma ho pensato, qui abbiamo solo una funzione, è solo per ottenere io con l'abitudine? – punstress

+1

@punstress: In sostanza lo è. Ed è una buona abitudine entrare. ;-) – Jon

+0

@Jon Essenzialmente è una buona pratica separare sempre l'interfaccia dall'implementazione, giusto? – NlightNFotis

6

Hai ragione, se questo è tutto encrypt.h dichiara, non è necessario includerlo nel file .c.

Lo fai per lo più per coerenza.

+0

Pensavo fosse qualcosa del genere, grazie. – punstress

4

Immaginate che si cambia encrypt.c a void encrypt(char *message, int i) { }

Se non si include encrypt.h non si noterà che l'altro i file nella tua applicazione non sono stati aggiornati per passare il nuovo parametro. Se aggiorni encrypt.h e encrypt.c allo stesso tempo il compilatore può fare il controllo per te.

+0

Stavo solo rileggendo questo dallo scorso anno, e mi piace il tuo punto. Grazie. – punstress

1

È buono stile. A volte, il file C con l'implementazione della funzione e il file C con l'uso della funzione condivide dichiarazioni comuni - tipi/strutture, Queste dichiarazioni condivise vengono posizionate nel file H. Per es.

[enc.h] 
typedef enum {S,F} Res; 
EN encode(); 

[enc.c] 
#include "enc.h" 
Res encode() { ... } 

[other.c] 
Res res; 
res = encode(); 
0

Poi si includere l'intestazione in un file .c un'altra * il compilatore sa in questo modo che in qualsiasi altro luogo è la definizione della funzione.

Questo ist come:

#include <stdio.h> 

int main (void) 
{ 
    afun(); 
    return 0; 
} 

void afun (void) 
{ 
    printf("hello\n"); 
} 

Ora il compilatore non sa cosa fare con aFun() nella funzione principale. Perché non è stato definito. Quindi condurrà a un errore del compilatore.

Quindi si aggiunge la dichiarazione all'inizio o bevore il primo utilizzo:

#include <stdio.h> 

void afun(void); 

int main (void) 
{ 
    afun(); 
    return 0; 
} 

void afun (void) 
{ 
    printf("hello\n"); 
} 

Conoscere il compilatore conosce il Deklaration di aFun e spera anythere altro la funzione è definita. Con i file di intestazione è possibile utilizzare il c-code precompilato. L'unica cosa che è necessaria al compilatore è la dichiarazione della funzione.

+1

L'OP ha detto: "Capisco perché avrei bisogno dei file di intestazione per risolvere il problema dell'utilizzo di una funzione prima che venga definita" nel suo post iniziale ... –

+0

Sì, vorrei mostrare: Con i file di intestazione è possibile utilizzare il c precompilato -codice. – Alex44

Problemi correlati