L'output di questo codice C è 49 ma qualcuno può spiegarmi come? [duplicare]

Jan 20 2021
#include <stdio.h>

#define CUBE(x) (x * x * x)

int main() {
    printf("%d", CUBE(4+5));
    return 0;
}

Risposte

5 MarkSouls Jan 20 2021 at 14:31

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)).

9 chqrlie Jan 20 2021 at 14:34

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.

3 Tecto Jan 20 2021 at 14:32

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)

3 SahadatHossain Jan 20 2021 at 14:31

è 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;
}
1 BasileStarynkevitch Jan 20 2021 at 14:29

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 .