_______________
< From *.c to *.i >
  ---------------
         \   ^__^ 
          \  (oo)\_______
             (__)\       )\/\
                 ||----w |
                 ||     ||

Per trasformare un codice sorgente in un eseguibile il compilatore svolge una serie di passi. Il primo è quello della preprocessing, durante il quale vengono eliminati i commenti[*] e svolte le direttive al preprocessore[*], come #include, #define, #ifdef ecc.

In questa fase è possibile creare un nuovo file che incorpora i file di header, e in cui le definizioni sono state sostituite con il loro valore.

Ad esempio consideriamo il file source.c un file con il seguente contenuto:

#ifndef RET
#define RET 0
#else
#define RET 1
#endif
int main()
{
        /* Ritorno al S.O. */
        return RET;
}

Per eseguire la sola fase di preprocessing basta eseguire il comando gcc con l’opzione -E. Con il seguente comando viene letto il file source.c, preprocessato ed infine viene creato il file preprocessed.i che contiene l’output del preprocessing.

gcc -E -o preprocessed.i source.c

Il contenuto di preprocessed.i avrà un aspetto del genere:

# 1 "source.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 31 "<command-line>"
# 1 "/usr/include/stdc-predef.h" 1 3 4
# 32 "<command-line>" 2
# 1 "source.c"

int main()
{

        return 0;
}

Ovvero un file pronto per essere preso in carico dalla successiva fase della compilazione ovvero la trasformazione di questo codice in Assembler, un linguaggio che ha praticamente una relazione 1 a 1 tra istruzione e il linguaggio macchina.