L'output di questo codice C è 49 ma qualcuno può spiegarmi come? [duplicare]
#include <stdio.h>
#define CUBE(x) (x * x * x)
int main() {
printf("%d", CUBE(4+5));
return 0;
}
Risposte
La macro trasformerà il codice in:
printf("%d", (4+5 * 4+5 * 4+5));
che è effettivamente:
printf("%d", 4 + (5*4) + (5*4) + 5); // 29
Se vuoi 9
ottenere il cubo 729
, dovresti scrivere CUBE((4+5))
.
Ecco come la macro viene espansa durante il processo di compilazione:
printf("%d", (4+5 * 4+5 * 4+5));
Poiché *
ha una precedenza maggiore di +
, questa espressione viene valutata come (4 + (5 * 4) + (5 * 4) + 5)
, producendo 49
invece del previsto 729
.
Per evitare tali problemi di precedenza degli operatori, tutti gli argomenti macro devono essere racchiusi tra parentesi nella definizione della macro così come nell'espressione stessa:
#define CUBE(x) ((x) * (x) * (x))
Si noti tuttavia che questa espansione di CUBE
valuta x
più volte, il che è un problema se l'argomento macro ha effetti collaterali, come CUBE(i++)
.
Per evitare tutti questi problemi, usa una funzione e lascia che il compilatore la ottimizzi:
int cube(int x) {
return x * x * x;
}
È possibile aggiungere static inline
prima di questa definizione di funzione, ma gli ottimizzatori moderni continueranno a incorporare la funzione senza di essa.
Il preprocessore C sostituirà letteralmente tutte le istanze di x con 4 + 5, ottenendo il seguente codice:
i = 4+5*4+5*4+5;
(prima moltiplicazione, poi addizione)
è necessario fornire l'input come CUBE((4+5))
se si desidera aggiungere i numeri e quindi inviare a CUBE
. Perché questo CUBE(4+5)
è fondamentalmente espanso in 4+5*4+5*4+5
quanto pone il tutto 4+5
al posto di x
. Quindi, 4+5*4+5*4+5
= 4+20+20+5
poiché la moltiplicazione viene prima e poi aggiungerli darà 49
.
Definire la macro come #define CUBE(x) ((x)*(x)*(x))
se effettivamente procedesse prima l' (4+5)
operazione per ogni, (x)
quindi eseguire l' *
operazione.
Un altro modo è usare semplicemente CUBE((4+5))
mentre si chiama la macro, fondamentalmente prima ha aggiunto i due numeri e (4+5)
= 9
e poi si fa CUBE(9)
, come:
#include<stdio.h>
#define CUBE(x) (x * x * x)
int main( )
{
printf("%d", CUBE((4+5)));
return 0;
}
Leggi moderna C , poi la n1570 progetto standard C, e la documentazione di GCC e GDB e di CPP . Vedere anche questo sito Web di riferimento C.
Prendi ispirazione da progetti open source esistenti, ad esempio su GitHub o software GNU .
Con un compilatore GCC recente , invocalo come gcc -Wall -Wextra -g
. Usa anche le -C -E
opzioni per ottenere il modulo preelaborato.
Potresti anche essere interessato dall'estensione statement-expr di GCC.
Tua CUBE(4+5)
è macro-espanso a 4+5*4+5*4+5
che viene calcolato come 4+(5*4)+(5*4)+5
secondo la precedenza di operatori C .
Considera l'idea di codificare una static inline
funzione come
static inline int cube(int x) { return x*x*x; }
o se hai bisogno di una macro, almeno
#define CUBE(X) ((X)*(X)*(X))
che non funzionerà bene per CUBE(i++)
(mentre con la inline
funzione, cube(i++)
fa quello che vuoi che faccia: incrementa i
una volta!).
A proposito, potresti usare GPP , o GNU m4 , (o il tuo generatore, o GNU bison ) per generare del codice C. Come regola pratica, pensa con AST s: quando generi codice C, emetti molte parentesi inutili, come ad esempio in Chicken Scheme , SWIG , o in CAIA o nel mio manydl.c
Potresti anche usare l' analizzatore statico Clang sul tuo codice (e forse Frama-C ).
Potresti essere interessato a leggere alcune linee guida di codifica come MISRA C o GNU .