首页 > 解决方案 > 为什么需要确保在包含使用它的预编译头文件之前不扩展 gcc 的 __COUNTER__ 宏?

问题描述

我遇到以下关于__COUNTER__的话:

必须注意确保在包含使用它的预编译头文件之前不扩展 __COUNTER__。否则,将不会使用预编译的头文件。

我写了一个简单的代码来测试:

$ cat a.h
void func()
{
    printf("%d\n", __COUNTER__);
}
func();

$ cat a.c
#include <stdio.h>


int main(void) {
    printf("%d\n", __COUNTER__);
    printf("%d\n", __COUNTER__);
    #include "a.h"
    printf("%d\n", __COUNTER__);
    return 0;
}

构建并运行它:

$ cc a.c
$ ./a.out 
0
1
2
3

它符合我的预期目标。那么如何理解“ Care must be taken to ensure that __COUNTER__ is not expanded prior to inclusion of precompiled headers which use it.”?

标签: cgcc

解决方案


您显示的代码通常使用头文件,而不是使用预编译的头文件。请注意,您引用的限制仅适用于预编译的标头。

原因其实很简单:__COUNTER__每次更改的替换文本都__COUNTER__被扩展了。当使用的头文件__COUNTER__被预编译时,在预编译时有效的替换文本将嵌入到预编译的头文件中。

如果您__COUNTER__在包含预编译标头之前在代码中展开,则正常使用标头与预编译标头的结果会有所不同:正常包含将使用__COUNTER__当前由包含之前的用法修改的值,而预编译版本将包含替换预编译标头时的文本。因此,不能使用预编译版本,因为它的内容是错误的。


推荐阅读