Questo è il processo:
source header source header header
\ / \ | //
\ / \ | //
PREPROCESSOR PREPROCESSOR
| |
V V
preprocessed code preprocessed code
| |
COMPILER COMPILER
| |
V V
object code object code
\ /
\ /
\ /
LINKER
|
V
executable
preelaborazione
#include
è per questo primo passo. Indica al preprocessore di elaborare il file specificato e inserire il risultato nell'output.
Se A
include B
e C
, e B
include C
, l'uscita del preprocessore per A
includerà il testo elaborato di C
due volte.
Questo è un problema, poiché genererà dichiarazioni duplicate. Un rimedio consiste nell'utilizzare le variabili del preprocessore per tenere traccia se il codice sorgente è stato incluso (aka header guards).
#ifndef EXAMPLE_H
#define EXAMPLE_H
// header contents
#endif
La prima volta, EXAMPLE_H
è indefinito, e il preprocessore si valutano il contenuto all'interno del blocco ifndef
/endif
. La seconda volta salterà quel blocco. Quindi l'output elaborato cambia e le definizioni sono incluse solo una volta.
Questo è così comune che esiste una direttiva non standard implementato da alcuni compilatori che è più breve e non richiede la scelta di una variabile preprocessore unico:
#pragma once
// header contents
si può capire come portatile si desidera che il C/Codice C++ e quale intestazione utilizzare.
Le protezioni delle intestazioni garantiscono che i contenuti di ciascun file di intestazione siano presenti al massimo una volta nel codice preelaborato per un'unità di traduzione.
Compilazione
il compilatore genera codice macchina dal C pre-elaborato/C++.
In genere, i file di intestazione includono solo dichiarazioni, non le definizioni effettive (ovvero le implementazioni). Il compilatore include una tabella dei simboli per tutto ciò che attualmente manca una definizione.
Linking
Il linker combina i file oggetto. Corrisponde alle definizioni (alias implementazioni) con i riferimenti alla tabella dei simboli.
È possibile che due file oggetto forniscano la definizione e che il linker ne esegua uno.Questo succede se hai inserito il codice eseguibile nelle intestazioni. Questo generalmente non accade in C, ma succede molto spesso in C++, a causa dei template.
Il "codice" di testa, se le dichiarazioni o definizioni, è incluso più volte in tutti i file oggetto, ma il linker si fonde tutto questo insieme, in modo che sia presente solo una volta nel file eseguibile. (Sono escluse le funzioni inline, che sono presenti più volte.)
* "un file di intestazione (con include guardie) verrà incluso solo una volta in un'unità di traduzione ma più volte nell'intero codice. ?"* Sì. Non una volta per programma, è (al massimo) una volta per unità di traduzione. – CoryKramer
Con le protezioni incluse, l'intestazione può ancora essere inclusa più volte anche in una unità di traduzione, ma la maggior parte di essa (la parte all'interno delle guardie) verrà saltata dopo la prima volta. Il preprocessore non si cura di dove è stato precedentemente incluso ... solo se la macro della guardia è stata ancora definita (cosa che accade la prima volta che viene inclusa se le protezioni sono configurate correttamente). – Dmitri
Grazie. Adoro questo sito :) risposte super veloci e ottime risposte. – Engineer999