C预处理器实际上是如何工作的?
我使代码片段更易于解释C预处理器实际上是如何工作的?,c,macros,C,Macros,我使代码片段更易于解释 // 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(
// 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
第一种是直观的,代码类型存在于多个地方,例如查找最大或最小数量。但是,我希望使用这种技术使代码干净易读,因此我用一个更短、更有意义的名称替换宏中的一些单词
AFAIK,C预处理器每个编译单元只运行一次,并且只执行字符串替换,但是为什么print_score
不能扩展到printf(“%d\n”,80)代码>
我想这就是更换程序:
#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
这是一个顺序问题。首先定义宏,score
在使用之前是未定义的。然后,当展开print\u score
时,它首先替换所有不存在的student\u-test\u score
实例。然后它会重新扫描结果,寻找更多要展开的宏,但没有宏,因为score
尚未定义且不再可用
即使您将#undef score
移动到print_score
的引用下方,它仍然不起作用,因为参数替换只发生一次(score
将展开,但student_test_score
不会展开)
请注意,score
未在定义时替换到print\u score
的主体中。只有在实例化宏时才会发生替换,这就是为什么#undef score
会导致score
宏没有任何效果
这些例子将使它更清楚。首先,考虑以下几点:
#define foo bar
#define baz(bar) (foo)
baz(123)
#define foo bar
#define baz(bar) (foo)
#undef foo
baz(123)
其扩展如下:
baz(123)
-> (foo)
-> (bar)
baz(123)
-> (foo)
扩展到此为止。参数替换是在展开foo
之前完成的,不会再次发生
现在考虑以下内容:
#define foo bar
#define baz(bar) (foo)
baz(123)
#define foo bar
#define baz(bar) (foo)
#undef foo
baz(123)
其扩展如下:
baz(123)
-> (foo)
-> (bar)
baz(123)
-> (foo)
扩展在此停止,因为不再定义foo
。其早期定义对baz
的定义没有影响,因为定义宏时不会发生宏替换。只有当它们被展开时才会发生这种情况。print_score(80);=>printf(“%d\n”,score)=>printf(“%d\n”,student\u score),所以这就是问题所在。@BlackMamba不会先print\u score(student\u score)printf(“%d\n”,score)
替换为print\u score(student\u考试成绩)printf(“%d\n”,student\u考试成绩)
“C预处理器只在每个编译单元运行一次”,并且“为什么不能将print\u分数扩展为printf(“%d\n”,80)”代码>?“后者正是因为前者。@Keivin Dong我认为它与解释顺序有关,score
为什么没有定义?我不确定预处理是否存在未定义的问题。这是一个排序问题<代码>#未定义分数
未定义分数
,在使用之前。请参阅我刚才添加的答案中的最后一段。#undef
的存在只是为了不影响以下代码。我理解您的要求。但它不像你想象的那样工作<代码>分数
将不会在打印分数
的主体中展开,直到打印分数
被实例化之后,但此时不再定义分数
。如果您查看预处理器的输出,就会明白。但这并不重要,因为即使定义了score
,它也不会替换参数。我开始使用cpp
检查唯一预处理的输出。我仍然不明白为什么第一个有效,但不是我的。第一个人不是也面临这个问题吗?