I made the code snippet simpler to explain
// Example 1
#define sum2(a, b) (a + b)
#define sum3(a, b, c) (sum2(a, sum2(b, c)))
sum3(1, 2, 3) // will be expanded to ((1 + (2 + 3)))
// Example 2
#define score student_exam_score
#define print_score(student_exam_score) printf("%d\n", score)
#undef score
print_score(80); // will be expanded to printf("%d\n", score);
// but not printf("%d\n", 80); that I expect
The first one is intuitive, and that kinds of codes exists in several places such as finding the maximum or minimum number. However, I want to use that technique to make my code clean and easy to read, so I replace the some words in a macro with a shorter and more meaningful name.
AFAIK, C preprocessor runs only once per compilation unit and only performs string replacement, but why print_score
cannot be expanded to printf("%d\n", 80);
?
This is the replacement procedure I guess:
#define score student_exam_score
#define print_score(student_exam_score) printf("%d\n", score)
#undef score
print_score(80);
// -->
#define score student_exam_score // runs this first
#define print_score(student_exam_score) printf("%d\n", student_exam_score) // changed
#undef score
print_score(80);
// -->
#define score student_exam_score
#define print_score(student_exam_score) printf("%d\n", student_exam_score) // then this
#undef score
printf("%d\n", 80); // changed
It's a sequencing issue. First the macros are defined, and score
is undefined before it is ever used. Then, when print_score
is expanded, it first substitutes all instances of student_exam_score
, of which there are none. It then rescans the result, looking for further macros to expand, but there are none since score
has been undefined and is no longer available.
Even if you moved #undef score
down below the reference to print_score
, it still wouldn't work since parameter substitution only happens once (score
would be expanded but student_exam_score
would not).
Note that score
is not substituted into the body of print_score
at the time is it defined. Substitution only happens when the macro is instantiated, which is why #undef score
results in the score
macro having no effect whatsoever.
These examples will make it clearer. First, consider the following:
#define foo bar
#define baz(bar) (foo)
baz(123)
This is expanded as follows:
baz(123)
-> (foo)
-> (bar)
Expansion stops here. Parameter substitution was done before foo
was expanded, and does not happen again.
Now consider the following:
#define foo bar
#define baz(bar) (foo)
#undef foo
baz(123)
This is expanded as follows:
baz(123)
-> (foo)
Expansion stops here because foo
is no longer defined. Its earlier definition had no effect on the definition of baz
, because macro substitution does not happen when macros are defined. It only happens when they are expanded.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With