Come programmatore mi è stato insegnato a preferire la parola chiave in linea alle definizioni macro per piccole funzioni. So che in linea è noto per essere più sicuro a causa delle definizioni delle macro che non eseguono alcun tipo di controllo, tuttavia mi viene detto che in linea è solo una richiesta per il compilatore di sostituire effettivamente il codice, e il compilatore non deve accettare quella richiesta, quindi mi chiedo anche le richieste di macro o sono garantiti per non avere un tempo eccessivo?
risposte:
8 per risposta № 1Le macro sono sostituzioni testuali eseguite primala fase di compilazione - non possono avere "overhead di run-time" nel modo in cui una chiamata di funzione potrebbe. Tuttavia, questo non è un buon motivo per utilizzare macro invece di funzioni, poiché i compilatori integreranno automaticamente funzioni anche senza inline
parola chiave con ottimizzazioni abilitate. Inoltre, utilizzando l'ottimizzazione del tempo di collegamento -flto
consentirà l'inlining tra le TU.
2 per risposta № 2
I macro sono cose in fase di compilazione. Non appaiono mai come macro nel codice compilato. Se definisci qualcosa del genere
#define MyVar 5
E tu fai nel codice:
double y = MyVar*MyVar;
Questo è esattamente come:
double y = 5*5;
Al momento della compilazione, il MyVar
la macro è sostituito dal valore che hai definito. Non c'è assolutamente nessun sovraccarico in fase di esecuzione.
1 per risposta № 3
Le macro sono una funzione di preprocessore.
Il preprocessore modifica il tuo programma in modo puramente testuale e puoi vederne i risultati se esegui il preprocessore separatamente.
Con gcc puoi farlo con entrambi gcc -E
o cpp
. Lo faccio abbastanza spesso quando eseguo il debug dei miei macro.
Esempio main.c:
#include <stdio.h>
#define MC_repeat(X)
for(int _i=0;_i<(X);_i++)
#define rt return
#define MC_xputs(X) if(0>puts(X)) rt -1;
int main()
{
MC_repeat(5)
MC_xputs("hello world");
rt 0;
}
Uscita di gcc -E main.c | tail
:
# 2 "main.c" 2
# 11 "main.c"
# 11 "main.c"
int main()
{
for(int _i=0;_i<(5);_i++)
if(0>puts("hello world")) return -1;;
return 0;
}
Quando si compila una fonte di questo tipo, è effettivamente come se si stesse eseguendo prima il preprocessore e poi i risultati del piping sul compilatore.
gcc non lo fa in questo modo (quindi ottieni messaggi di errore migliori), ma puoi forzarlo a:
#actually pipes preprocessor output to the compiler proper
gcc -E main.c | gcc -x cpp-output