Wynik tego kodu C to 49, ale czy ktoś może mi wyjaśnić, jak to zrobić? [duplikować]

Jan 20 2021
#include <stdio.h>

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

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

Odpowiedzi

5 MarkSouls Jan 20 2021 at 14:31

Makro zamieni kod na:

printf("%d", (4+5 * 4+5 * 4+5));

czyli skutecznie:

printf("%d", 4 + (5*4) + (5*4) + 5); // 29

Jeśli chcesz 9dostać kostkę 729, powinieneś napisać CUBE((4+5)).

9 chqrlie Jan 20 2021 at 14:34

Oto jak makro jest rozwijane podczas procesu kompilacji:

printf("%d", (4+5 * 4+5 * 4+5));

Ponieważ *ma wyższy priorytet niż +, to wyrażenie jest oceniane jako (4 + (5 * 4) + (5 * 4) + 5), tworząc 49zamiast oczekiwanego 729.

Aby uniknąć takich problemów z pierwszeństwem operatorów, wszystkie argumenty makr muszą być umieszczone w nawiasach w definicji makra, a także w samym wyrażeniu:

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

Zwróć jednak uwagę, że to rozszerzenie wartości jest CUBEobliczane xwiele razy, co jest problemem, jeśli argument makro ma skutki uboczne, takie jak CUBE(i++).

Aby uniknąć wszystkich tych problemów, użyj funkcji i pozwól kompilatorowi ją zoptymalizować:

int cube(int x) {
    return x * x * x;
}

Możesz dodać static inlineprzed tą definicją funkcji, ale nowoczesne optymalizatory nadal będą wbudowywać funkcję bez tego.

3 Tecto Jan 20 2021 at 14:32

Preprocesor C dosłownie zamieni wszystkie wystąpienia x na 4 + 5, w wyniku czego otrzymamy następujący kod:

i = 4+5*4+5*4+5;

(najpierw mnożenie, potem dodawanie)

3 SahadatHossain Jan 20 2021 at 14:31

musisz podać dane wejściowe, takie jak, CUBE((4+5))jeśli chcesz dodać liczby, a następnie wysłać do CUBE. Ponieważ th CUBE(4+5)jest zasadniczo rozszerzany, 4+5*4+5*4+5ponieważ ustawia całość 4+5w miejscu x. Tak więc, 4+5*4+5*4+5= 4+20+20+5ponieważ mnożenie jest pierwsze, a następnie dodanie ich da 49.

Zdefiniuj makro tak #define CUBE(x) ((x)*(x)*(x)), jak faktycznie najpierw wykonaj (4+5)operację dla każdego, (x)a następnie wykonaj *operację.

Innym sposobem jest po prostu użycie CUBE((4+5))podczas wywoływania makra, w zasadzie najpierw dodano dwie liczby i (4+5)=, 9a następnie wykonaj CUBE(9), na przykład:

#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

Przeczytaj Modern C , a następnie projekt standardu C n1570 oraz dokumentację GCC i GDB i CPP . Zobacz także tę witrynę referencyjną C.

Czerp inspirację z istniejących projektów open source, np. Na github lub oprogramowania GNU .

W przypadku najnowszego kompilatora GCC wywołaj go jako gcc -Wall -Wextra -g. Skorzystaj również z -C -Eopcji, aby uzyskać wstępnie przetworzony formularz.

Możesz być również zainteresowany rozszerzeniem instrukcji-expr w GCC.

Twój CUBE(4+5)jest makro-rozszerzony do 4+5*4+5*4+5którego jest obliczana jako 4+(5*4)+(5*4)+5według pierwszeństwa operatorów C .

Rozważ zakodowanie static inlinefunkcji takiej jak

static inline int cube(int x) { return x*x*x; }

lub przynajmniej jeśli potrzebujesz makra

#define CUBE(X) ((X)*(X)*(X))

co nie będzie dobrze działać CUBE(i++)(gdy jest z inlinefunkcją, cube(i++)robi to, co chcesz: inkrementuj iraz!).

Przy okazji, możesz użyć GPP lub GNU m4 (lub własnego generatora lub GNU bison ) do wygenerowania kodu C. Z reguły myśl z AST s: kiedy generujesz kod C, emituj dużo bezużytecznych nawiasów, jak np. W Chicken Scheme , SWIG , lub w CAIA lub w moim manydl.c

Możesz również użyć analizatora statycznego Clang w swoim kodzie (i być może Frama-C ).

Możesz być zainteresowany przeczytaniem kilku wskazówek dotyczących kodowania, takich jak MISRA C lub GNU .