Macro funzioni.

Ricorda la direttiva del preprocessore #define. La caratteristica fondamentale di come funziona #define è che sostituisce una sequenza di caratteri con quello che vi scriviamo, e questo permette di creare le cosiddette macro funzioni, che non vengono create come funzioni, ma vengono inserite nel codice durante la compilazione. Ad esempio, una macro che somma due numeri sarà simile a questa:
#define sum(x, y) ((x)+(y))
Gli "argomenti" della funzione macro devono essere racchiusi tra parentesi (come (x)+(y) sopra), altrimenti la macro potrebbe essere imprevedibile se l'argomento non è un singolo numero, ma un'espressione.
È anche desiderabile prendere l'intero corpo della funzione macro tra parentesi, ( (x) + (y) ) come sopra, altrimenti potresti incorrere in una situazione spiacevole con l'ordine di calcolo. Ad esempio, nel codice utilizziamo sum(x, y) * 5. La macro si espanderà a (x + y) * 5. Se il corpo della macro non ha parentesi, risulterà x + y * 5, che ha un significato completamente diverso!
In fase di compilazione in questo documento di codice, tutte le occorrenze di sum(x, y) saranno sostituite da x + y, quindi sarà la somma.
#define sum(x, y) ((x)+(y))
void setup() 
     byte a = 5; 
     byte b = 7; 
     byte c = sum(a, b);
     byte d = sum(5, 7);
}
void loop() 
{
}
Perché è necessario? Una normale funzione con un nome ha un proprio "indirizzo" in memoria e ogni volta che la funzione viene chiamata, il core del microcontrollore accede a questo indirizzo, il che richiede del tempo. Una funzione macro viene "incorporata" nel codice del programma ed eseguita immediatamente. Allo stesso tempo, se una funzione macro viene chiamata in più punti del programma, occuperà più spazio di una singola funzione regolare, perché tutte le chiamate verranno sostituite da un codice. Ha senso creare macro per funzioni semplici, per funzioni chiamate raramente e in quei luoghi in cui le massime prestazioni sono importanti. Ogni ciclo del processore è importante. Ad esempio nelle funzioni computazionali.
Il "linguaggio" di Arduino ha una serie di strumenti già pronti che sembrano essere funzioni ma in realtà sono macro. Esaminiamo Arduino.h e vediamo quanto segue:
#define min(a,b) ((a)<(b)?(a):(b))
#define max(a,b) ((a)>(b)?(a):(b))
#define abs(x) ((x)>0?(x):-(x))
#define constrain(amt,low,high) ((amt)<(low)?(low):((amt)>(high)?(high):(amt)))
#define round(x) ((x)>=0?(long)((x)+0.5):(long)((x)-0.5))
#define radians(deg) ((deg)*DEG_TO_RAD)
#define degrees(rad) ((rad)*RAD_TO_DEG)
#define sq(x) ((x)*(x))
E puoi anche "avvolgere la stringa" per creare funzioni macro con una grande quantità di testo, il trasferimento viene eseguito utilizzando una barra rovesciata - \.
#define printWords() \ 
Serial.print("Hello, "); \ 
Serial.print("World"); \ 
Serial.println("!");
void setup() 
     Serial.begin(9600); 
     printWords();
}
void loop() 
{
}
Attenzione, sull'ultima stringa il trasferimento non è più necessario! Pertanto, mentre il preprocessore è in esecuzione, tutte le chiamate alla "funzione" printWords() verranno sostituite dalle stringe di codice specificate. Puoi passare argomenti allo stesso modo:
#define printWords(site) \ 
Serial.print("Electron"); \ 
Serial.print(site);
void setup() 
     Serial.begin(9600); 
     printWords(32); 
}
void loop() 
{
}  
Crea il tuo sito web gratis! Questo sito è stato creato con Webnode. Crea il tuo sito gratuito oggi stesso! Inizia