Corso C avanzato su Raspberry PI: Il preprocessore

Da questo numero inizia, a grande richiesta, il corso di livello avanzato sulla programmazione in linguaggio C, con il Raspberry Pi. Per la comprensione di esso si consiglia la preventiva assimilazione del precedente corso base, composto da dodici puntate. In questo modo si potranno seguire, in maniera serena e senza difficoltà, i concetti e le spiegazioni, proprio come la trama di un film a puntate. Ci auguriamo che le dodici puntate che stiamo andando a seguire abbiano lo stesso successo delle precedenti. Al solito, sono ben accetti commenti, consigli e delucidazioni sugli argomenti trattati. In questa puntata affronteremo la tematica del preprocessore, una sorta di controllo sul linguaggio e sui suoi comportamenti. Auguriamo a tutti buona lettura e buono studio.

Introduzione

Il preprocessore serve ad effettuare una sorta di controllo che viene effettuato sul codice sorgente del programma, prima della compilazione vera e propria. In pratica, esamina il listato e restituisce un altro sorgente, più "filtrato", pronto per poter essere reso eseguibile dal compilatore, come evidenziato dallo schema a blocchi di cui in figura 1. Il suo nome, in effetti, mette un po' paura e fa pensare che si tratti di qualcosa che interferisca con il processore o la CPU. Nulla di tutto questo. Esso ha "solo" il compito di esaminare preventivamente, ed eventualmente modificarlo, il listato sorgente, in linguaggio C.

 

Figura 1: Il Preprocessore.

Figura 1: Il Preprocessore.

 

Il preprocessore ha il compito, dunque, di esaminare il listato, cercare eventuali direttive speciali (vedremo più avanti di che si tratta) e, in base ad esse, ricostruire un nuovo listato, da fornire in pasto, in maniera definitiva, al compilatore. Quest'ultimo, dunque, riceve una nuova versione di programma, leggermente differente da quella scritta dal programmatore.

Quali compiti esegue il preprocessore?

Quale analizzatore di sorgente, il preprocessore agisce direttamente sul testo del listato, applicando alcune modifiche. In particolare:

  • Riesce ad inserire nel testo altri elementi esterni, prelevati da files diversificati;
  • Elimina dal testo alcune porzioni di codice, se si verificano alcuni eventi (di macchina, di ambiente, di utente, ecc);
  • Sostituisce parti di testo, anche molto estese, con altre più comode e logiche.

Questi sono i compiti principali ma, come vedremo, il preprocessore sa fare molto di più. Inoltre il suo utilizzo rende il programma molto più trasportabile per altri sistemi e piattaforme diversificate.

Le direttive

Si tratta di comandi magici che, inseriti in opportune posizioni nell'ambito del listato sorgente, riescono a produrre effetti grandiosi. Una direttiva inizia sempre con il simbolo di cancelletto (#) seguita da una parola chiave legata alla funzionalità prevista. Nel proseguo dell'articolo studieremo un bel po' di direttive, sapendo che esse sono davvero tante. Nella fattispecie, ecco quali tratteremo:

  • #include
  • #define
  • #if
  • #ifdef
  • #error

Ovviamente ne esistono delle altre.

La direttiva #include

Probabilmente essa è la direttiva più utilizzata nella programmazione. Ha il compito di includere nel proprio listato, una porzione di testo "pescato" in un altro file presente nel disco. Con un esempio chiariamo immediatamente il concetto. Si supponga di aver creato il file "pippo.h" contenente i seguenti prototipi:

int perimetro(int base, int altezza);
int strlen(char[]);
void stampa(int variabile);

Senza la direttiva #include, sarebbe necessario scriverli sempre nel proprio listato, all'inizio di esso. Si capisce subito di quanto la procedura sia alquanto scomoda, specialmente se il numero dei prototipi fosse molto alto. Utilizzando tale direttiva, invece, il programma risulterebbe molto più snello:

#include "pippo.h"
void main() {
   /* codice.... */
}

e risulterebbe equivalente al seguente listato:

int perimetro(int base, int altezza);
int strlen(char[]);
void stampa(int variabile);
void main() {
   /* codice.... */
}

La direttiva #include accetta due sintassi diverse:

  • #include "pippo.h"
  • #include <pippo.h>

La prima si usa quando il file pippo.h si trova in una posizione ben precisa e richiede l'indicazione del relativo percorso, se il file non si trova nella cartella corrente. La seconda si riferisce [...]

ATTENZIONE: quello che hai appena letto è solo un estratto, l'Articolo Tecnico completo è composto da ben 2220 parole ed è riservato agli abbonati MAKER. Con l'Abbonamento avrai anche accesso a tutti gli altri Articoli Tecnici MAKER e potrai fare il download (PDF) dell'EOS-Book del mese. ABBONATI ORA, è semplice e sicuro.

Abbonati alle riviste di elettronica

4 Commenti

  1. Maurizio Di Paolo Emilio Maurizio Di Paolo Emilio 5 giugno 2018
  2. Giovanni Di Maria Giovanni Di Maria 5 giugno 2018
  3. enzocavallaro 19 luglio 2018

Scrivi un commento

EOS-Academy

Ricevi GRATIS le pillole di Elettronica

Ricevi via EMAIL 10 articoli tecnici di approfondimento sulle ultime tecnologie