15.4.6 C

Il linguaggio di programmazione per antonomasia dei sistemi Unix-like è il C. Nato negli anni ’70, per le sue caratterisitiche di versatilità, controllo ed efficienza è divenuto in breve tempo uno dei linguaggi più utilizzati per la scrittura di programmi a tutti i livelli, tanto che molti dei sistemi operativi moderni sono stati scritti in questo linguaggio di programmazione. È stato pure redatto uno standard in proposito da ANSI e dall’ISO negli anni ’89-’90.

Un esempio di semplice programma C è quello seguente

#include <stdio.h>
main()
{
printf("Salve mondo!\n");
}
che visualizzerà sullo schermo la scritta “Salve mondo!”. L’inizio dell’esecuzione di un programma C è la prima istruzione della funzione main(). La direttiva #include permette di includere altri file all’interno di quello nel quale è memorizzato il codice sorgente considerato: in questo caso viene incluso il file stdio.h, dalla directory di inclusione standard.

Come si avrà avuto modo di constatare dagli esempi riportati nelle sezioni precedenti, il linguaggio C privilegia la velocità: in realtà le operazioni possono essere scritte in maniera più o meno “criptica”17, ma quelle più criptiche sono generalmente anche quelle che producono un codice macchina più snello e quindi più veloce da eseguire. Ad esempio l’operazione di incremento a++ è logicamente analoga a a = a + 1, ma mentre la prima viene tradotta con una sola istruzione del linguaggio macchina, per la seconda ce ne vogliono di più, anche se il risultato ottenuto è lo stesso: incrementare di un’unità il contenuto della variabile a.

Oltre alle caratterisitiche di linguaggio di alto livello (costrutti chiave della programmazione strutturata, strutture dati, ...), il linguaggio C presenta anche alcune caratteristiche di linguaggio di basso livello, come l’uso di indirizzi di memoria (i puntatori) con i relativi meccanismi di reference e dereference18 e la possibilità di utilizzare direttamente i registri della CPU nonché di scrivere dei blocchi di istruzioni assembly direttamente all’interno del codice sorgente C.

È inoltre possibile creare delle “macro” che vengono sostituite durante la compilazione. Ad esempio, scrivendo la direttiva

                                                                        
                                                                        
#define TEST 1
il compilatore, ancora prima di tradurre le istruzioni del programma in codice macchina (si parla infatti in tal caso di preprocessore), provvederà alla sostituzione della parola TEST all’interno del programma stesso con il valore ad essa associato dalla macro, cioè 1. Si noti che in questo caso TEST non è una variabile (né tantomeno una costante) ma è come se da un editor di testo si eseguisse una sostituzione nel corpo del programma di tutte le occorrenze della stringa TEST con la stringa 1. Successivamente il compilatore tradurrà in linguaggio macchina il file risultante dopo la sostituzione (il file sorgente non subirà però alcuna modifica). Questa impostazione può risultare molto utile per utilizzare costanti senza sprecare spazio di memoria, ma soprattutto permette di parametrizzare opportune impostazioni di compilazione in modo da ottenere caratteristiche diverse dipendentemente dal valore impostato in opportune macro.

[da completare ...]