c - 为什么需要确保在包含使用它的预编译头文件之前不扩展 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.
”?
解决方案
您显示的代码通常使用头文件,而不是使用预编译的头文件。请注意,您引用的限制仅适用于预编译的标头。
原因其实很简单:__COUNTER__
每次更改的替换文本都__COUNTER__
被扩展了。当使用的头文件__COUNTER__
被预编译时,在预编译时有效的替换文本将嵌入到预编译的头文件中。
如果您__COUNTER__
在包含预编译标头之前在代码中展开,则正常使用标头与预编译标头的结果会有所不同:正常包含将使用__COUNTER__
当前由包含之前的用法修改的值,而预编译版本将包含替换预编译标头时的文本。因此,不能使用预编译版本,因为它的内容是错误的。
推荐阅读
- r - 根据另一列中的 AND 逻辑/条件过滤一列中重复出现的行
- json - 将 JSON 转换为 Python 字典(寻找更好的方法)
- python - 使用python中该列唯一值的动态列表按列拆分数据框
- excel - VBA - 检测编译失败的方法
- rest - 包装响应对象的 RAML Trait(用于定义 REST API)
- css - 使用 Chart.js 发布定位雷达图
- python - sqlalchemy with_for_update 导致选择在会话中不起作用
- javascript - 相同的点击事件处理程序注册两次
- pandas - 提取与 pandas.series 中的数字相对应的数据框列中的值 - 并转移到新系列
- python - 分组方式/枢轴