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);
?
AFAIK, C预处理器每个编译单元只运行一次,并且只执行字符串替换,但是为什么不能将print_score扩展到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
1 个解决方案
#1
3
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.
这是一个排序问题。首先定义宏,在使用之前未定义score。然后,当print_score扩展时,它首先替换student_exam_score的所有实例,其中没有实例。然后重新扫描结果,寻找进一步的宏来展开,但是由于score未定义且不可用,所以没有任何宏。
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).
即使您将#undef score向下移动到print_score引用以下,它仍然不能工作,因为参数替换只发生一次(将扩展score,但student_exam_score不会)。
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.
注意,在定义print_score时,不会将score替换为print_score主体。替换只在实例化宏时发生,这就是为什么#undef score会导致score宏没有任何效果。
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.
扩张停止在这里。参数替换是在foo扩展之前完成的,不会再次发生。
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.
扩展在这里停止,因为foo不再定义。它的早期定义对baz的定义没有影响,因为在定义宏时不会发生宏替换。只有当它们展开时才会发生。
#1
3
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.
这是一个排序问题。首先定义宏,在使用之前未定义score。然后,当print_score扩展时,它首先替换student_exam_score的所有实例,其中没有实例。然后重新扫描结果,寻找进一步的宏来展开,但是由于score未定义且不可用,所以没有任何宏。
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).
即使您将#undef score向下移动到print_score引用以下,它仍然不能工作,因为参数替换只发生一次(将扩展score,但student_exam_score不会)。
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.
注意,在定义print_score时,不会将score替换为print_score主体。替换只在实例化宏时发生,这就是为什么#undef score会导致score宏没有任何效果。
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.
扩张停止在这里。参数替换是在foo扩展之前完成的,不会再次发生。
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.
扩展在这里停止,因为foo不再定义。它的早期定义对baz的定义没有影响,因为在定义宏时不会发生宏替换。只有当它们展开时才会发生。