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 9ottenere 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 49invece 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 CUBEvaluta xpiù 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 inlineprima 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+5quanto pone il tutto 4+5al posto di x. Quindi, 4+5*4+5*4+5= 4+20+20+5poiché 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)= 9e 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 -Eopzioni 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+5che viene calcolato come 4+(5*4)+(5*4)+5secondo la precedenza di operatori C .
Considera l'idea di codificare una static inlinefunzione 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 inlinefunzione, cube(i++)fa quello che vuoi che faccia: incrementa iuna 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 .