Wynik tego kodu C to 49, ale czy ktoś może mi wyjaśnić, jak to zrobić? [duplikować]
#include <stdio.h>
#define CUBE(x) (x * x * x)
int main() {
printf("%d", CUBE(4+5));
return 0;
}
Odpowiedzi
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 9
dostać kostkę 729
, powinieneś napisać CUBE((4+5))
.
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 49
zamiast 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 CUBE
obliczane x
wiele 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 inline
przed tą definicją funkcji, ale nowoczesne optymalizatory nadal będą wbudowywać funkcję bez tego.
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)
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+5
ponieważ ustawia całość 4+5
w miejscu x
. Tak więc, 4+5*4+5*4+5
= 4+20+20+5
ponieważ 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)
=, 9
a 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;
}
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 -E
opcji, 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+5
którego jest obliczana jako 4+(5*4)+(5*4)+5
według pierwszeństwa operatorów C .
Rozważ zakodowanie static inline
funkcji 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 inline
funkcją, cube(i++)
robi to, co chcesz: inkrementuj i
raz!).
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 .