Missing parentheses in a macro can change expression precedence.

text substitution A macro expands as text, so operator precedence still matters afterward.
safer macro Wrap parameters and the full replacement expression in parentheses.
direct comparison The replay compares the expanded bad and good expressions directly.

Macro Pitfall

value
macro_pitfall.c
Replay: real traced execution (multi-file project)
#include <stdio.h>

#define BAD_TRIPLE(n) n * 3
#define GOOD_TRIPLE(n) ((n) * 3)

int main(void) {
    int value = 2;
    int bad = value + 1 * 3;
    int good = ((value + 1) * 3);

    printf("bad=%d good=%d\n", bad, good);
    return 0;
}
#include <stdio.h>

#define BAD_TRIPLE(n) n * 3
#define GOOD_TRIPLE(n) ((n) * 3)

int main(void) {
    int value = 4;
    int bad = value + 1 * 3;
    int good = ((value + 1) * 3);

    printf("bad=%d good=%d\n", bad, good);
    return 0;
}
#include <stdio.h>

#define BAD_TRIPLE(n) n * 3
#define GOOD_TRIPLE(n) ((n) * 3)

int main(void) {
    int value = 5;
    int bad = value + 1 * 3;
    int good = ((value + 1) * 3);

    printf("bad=%d good=%d\n", bad, good);
    return 0;
}
  1. value ← 2, bad ← 5, good ← 9

    6int main(void) {7    int value→ 2 = 2; //@value=4, 58    int bad→ 5 = value2 + 1 * 3;9    int good→ 9 = ((value2 + 1) * 3);1011    printf("bad=%d good=%d\n", bad5, good9);12    return 0;13}
    outputbad=5 good=9
  1. value ← 4, bad ← 7, good ← 15

    6int main(void) {7    int value→ 4 = 4;8    int bad→ 7 = value4 + 1 * 3;9    int good→ 15 = ((value4 + 1) * 3);1011    printf("bad=%d good=%d\n", bad7, good15);12    return 0;13}
    outputbad=7 good=15
  1. value ← 5, bad ← 8, good ← 18

    6int main(void) {7    int value→ 5 = 5;8    int bad→ 8 = value5 + 1 * 3;9    int good→ 18 = ((value5 + 1) * 3);1011    printf("bad=%d good=%d\n", bad8, good18);12    return 0;13}
    outputbad=8 good=18