Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/gwt/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C预处理器实际上是如何工作的?_C_Macros - Fatal编程技术网

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
检查唯一预处理的输出。我仍然不明白为什么第一个有效,但不是我的。第一个人不是也面临这个问题吗?