Klasycznym przykładem jest makro obliczyć maksymalnie dwóch wartości:
#define MAX(a, b) ((a) > (b) ? (a) : (b))
Teraz pozwala „nazywają” makro tak:
int x = 5;
int y = 7;
int z = MAX(x++, y++);
Teraz jeśli MAX
było normalne funkcjonowanie, spodziewalibyśmy się, że x
i y
zostaną inkrementowane raz, prawda? Jednak, ponieważ jest to makro „CALL” zastępuje się następująco:
int z = ((x++) > (y++) ? (x++) : (y++));
Jak widać, zmienna y
będzie zwiększany dwukrotnie, raz w warunku, a raz jako końcowego wyniku ternary operator.
Jest to wynik wyrażenia z efektami ubocznymi (wyrażenie po inkrementacji) i rozwinięciem makra.
W powiązanej notatce są też inne niebezpieczeństwa związane z makrami. Na przykład, weźmy to proste makro:
#define MUL_BY_TWO(x) (x * 2)
Wygląda prosto, prawda? Ale teraz co, jeśli używamy go tak:
int result = MUL_BY_TWO(a + b);
To rozszerzy jak
int result = (a + b * 2);
A jak mam nadzieję, że wie, mnożenie mają wyższy priorytet niż Dodatkowo, więc wyrażenie a + b * 2
jest równoważna a + (b * 2)
, prawdopodobnie nie to, co zamierzał autor makr. Dlatego argumenty makra należy umieścić wewnątrz własnych nawiasach:
#define MUL_BY_TWO(x) ((x) * 2)
Następnie ekspansja będzie
int result = ((a + b) * 2);
który jest prawdopodobnie poprawne.
http://stackoverflow.com/questions/7299286/whats-the-side-effect-the-following-macro- in-cbedded-c jest dobrym przykładem. – Downvoter