12.6. Stolpersteine
- Ist der Wert einer Konstanten nicht eine einfache Zahl, sondern ein Ausdruck, dann sollten Sie ihn bei der Definition unbedingt in Klammern setzen. Beachten Sie hierzu folgendes Fragment:
#define MAX_VAL 20 + 10
.
.
/* Das Resultat unten ist nicht 10*30, also 300,
* sondern 10 * 20 + 10, mithin 210! */
printf("Das Resultat ist: %d", 10 * MAX_VAL);
/* besser wäre daher:
* #define MAX_VAL (20 + 10)
*/
- Probleme ergeben sich erst recht, sobald Sie Ausdrücke als Argumente von Makros übergeben. Damit bei der Expansion eines Makros nicht unerwartete Resultate auftreten, sollten bei der Definition alle Parameter-Variablen in Klammern gesetzt werden.
- Schwer auffindbare Fehler können entstehen, sobald Sie Schlüsselwörter oder Namen für Bibliotheksfunktionen mit #define neu definieren. Vermeiden Sie daher unbedingt Anweisungen wie
#define strcpy(S1, S2) my_strcpy(S1, S2, sizeof(S1))
- Während es unproblematisch ist, Funktionsaufrufe als Argumente von Funktionen zu übergeben (z.B. putchar( getchar()) ), kann der gleiche Vorgang bei Makros schnell zu Problemen führen. Im folgenden Fragment meldet der Compiler einen Syntaxfehler, da Anweisungsblöcke als Argumente ja nicht zulässig sind. Daß die erstbeste Lösung, nämlich das Weglassen der geschweiften Klammern, keine gute Idee ist, zeigt dann der nächste Stolperstein.
#define SWAP(x,y) { \
int iTemp = x; \
x = y; \
y = iTemp; \
}
.
.
/* Fehler ! */
printf("Vertausche: %d vs. %d", SWAP(iFirst, iSecond));
- Besteht ein Makro aus mehreren Anweisungen, dann sollten diese zu einem Anweisungsblock zusammengefaßt werden, weil sonst die Makro-Expansion wiederum unerwartete Resultate nach sich ziehen kann. Beachten Sie das folgende Fragment:
#define PANIC fputs("Fataler Fehler", stderr);\
exit(EXIT_FAILURE);
.
.
if( iCount > MAX_VALUE )
PANIC;
/* Dies wird expandiert zu:
* if( iCount > MAX_VALUE )
* fputs("Fataler Fehler", stderr);
* exit(EXIT_FAILURE);
* Da die gescheiften Klammern fehlen, hängt
* nur fputs() von der if-Anweisung ab, exit()
* wird aber immer ausgeführt!
*/