C预处理器是如何工作的?

时间:2023-01-09 19:43:33

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的定义没有影响,因为在定义宏时不会发生宏替换。只有当它们展开时才会发生。