Per prima cosa come funziona #define?
Si tratta di una direttiva del preprocessore quindi la sua esecuzione viene interpretata prima della compilazione effettiva. Il preprocessore nasce con lo scopo di modificare il sorgente da compilare, semplificando sostanzialmente sostituzioni ed inclusioni di files ai programmatori.
#define permette di creare una macro od una costante che prima della compilazione viene espansa nel sorgente. Perché pericolosa? Perché sfugge al controllo del C++ e gli errori che derivano dal suo utilizzo in modo non appropiato a volte sono difficili da codificare. In altri casi come mostrerò sono praticamente inscovabili.
Immaginate il seguente programma:
- Codice: Seleziona tutto
#define HELLO 0x500
//...
int newValue=HELLO;
fino a qua sembra andare tutto bene no?
In effetti l'uso delle costanti è il più sicuro perché solitamente non provoca grossi problemi. Mettere i nomi in maiuscolo poi ci aiuta a capire che quella è una costante #define in casi come
- Codice: Seleziona tutto
HELLO=1250;
e anche se l'errore non sarà immediato, in fondo stiamo associando un numero ad un numero, non un numero ad una costante, comunque si riesce a trovarlo.
Tuttavia alcune delle caratteristiche avanzate che il C++ supporta sulle costanti ci saranno precluse e si evidenziano limiti con costanti di tipi chiaramente non nativi.
I problemi arrivano quando si usano le macro con troppa leggerezza.
- Codice: Seleziona tutto
#define OFF_POS(x,y) 0xb8000+(y*80+x)*2
//Questa macro potrebbe essere usata per ottenere la posizione di memoria si cui scrivere un carattere sullo schermo
//...
char *vgaMem=(char*)0xb8000;
vgaMem[OFF_POS(10,10)]='H';
vgaMem[OFF_POS(10,10)+1]=42;
//MI ha stampato una H colorata sullo schermo
Tutto ok? Sembrerebbe funzionare vero? Ora guardate questo...
- Codice: Seleziona tutto
#define OFF_POS(x,y) 0xb8000+(y*80+x)*2
//Questa macro potrebbe essere usata per ottenere la posizione di memoria si cui scrivere un carattere sullo schermo
//...
char *vgaMem=(char*)0xb8000;
int verticalOffset=5;
vgaMem[OFF_POS(10,verticalOffset+2)]='H';
vgaMem[OFF_POS(10,verticalOffset+2)+1]=42;
//MI ha stampato una H colorata sullo schermo
La stampa sulla 8° riga? No mi dispiace... finirà da qualche parte della terza. perché in realtà il compilatore senza generare errori giustamente ha fatto questo
- Codice: Seleziona tutto
vgaMem[ 0xb8000+(5+2*80+10)*2]='H';
Senza contare le precedenze degli operatori perché il preprocessore è stupido copia e basta quello che gli dite. Ora sullo schermo vedreste qualcosa che non va... ma in altri contensti questo errore sarebbe invisibile e non genererebbe errori di compilazione. Ed in esecuzione si presenterebbe solo a volte.
Chiaramente possiamo correggere il nostro #define
- Codice: Seleziona tutto
#define OFF_POS(x,y) 0xb8000+((y)*80+(x))*2
Anzi fareste ancora meglio a mettere tutto fra parentesi
- Codice: Seleziona tutto
#define OFF_POS(x,y) (0xb8000+((y)*80+(x))*2)
Così è abbastanza sigillato. Ora... perché correre questo rischio quando esiste una cosa chiamata funzione inline? Eccola
- Codice: Seleziona tutto
inline unsigned int OFF_POS(unsigned int x, unsigned int y){return 0xb8000+(y*80+x)*2;}
Ecco il motivo di usare il C++ anziché il preprocessore, si fanno rientrare la gestione degli errori e dei bug all'interno del linguaggio stesso. Esistono caratteristiche del preprocessore utilissime come gli operatori # e ##, insostituibili è vero. Ciò che è sostituibile però sostituiamolo ;)

Elettrotecnica e non solo (admin)
Un gatto tra gli elettroni (IsidoroKZ)
Esperienza e simulazioni (g.schgor)
Moleskine di un idraulico (RenzoDF)
Il Blog di ElectroYou (webmaster)
Idee microcontrollate (TardoFreak)
PICcoli grandi PICMicro (Paolino)
Il blog elettrico di carloc (carloc)
DirtEYblooog (dirtydeeds)
Di tutto... un po' (jordan20)
AK47 (lillo)
Esperienze elettroniche (marco438)
Telecomunicazioni musicali (clavicordo)
Automazione ed Elettronica (gustavo)
Direttive per la sicurezza (ErnestoCappelletti)
EYnfo dall'Alaska (mir)
Apriamo il quadro! (attilio)
H7-25 (asdf)
Passione Elettrica (massimob)
Elettroni a spasso (guidob)
Bloguerra (guerra)
