c - C 预处理输出包含包含文件的重新定义
问题描述
我对进一步修改 C 预处理代码有一个坏(好?)的想法(称之为思想实验。)
为了实现这一目标,我得到了以下 shell 命令序列。请注意,我没有对预处理代码添加任何修改,但保留了这样做的能力:
#!/bin/bash
gcc -E debug/*.h debug/*.c src/* > build/main.i
#Command to modify build/main.i in future
gcc -Wpointer-arith -Wall ./build/main.i -o ./bin/main.exe
但是,在运行最后一条命令编译代码时,会产生一堆重定义错误。下面是一个例子。甚至 C 标准函数也在做同样的事情。
In file included from src/String.c:3:
src/String.h:32:3: error: conflicting types for 'String'
32 | } String;
| ^~~~~~
In file included from debug/StringDebug.c:5:
debug/../src/String.h:32:3: note: previous declaration of 'String' was here
32 | } String;
| ^~~~~~
...many many more...
<path>\mingw\include\stdlib.h:916:61: error: redefinition of 'setenv'
916 | __cdecl __MINGW_NOTHROW int setenv( const char *__n, const char *__v, int __f )
| ^~~~~~
In file included from debug/../src/Object.h:4,
from debug/BasicTypeDebug.c:2:
<path>\mingw\include\stdlib.h:916:61: note: previous definition of 'setenv' was here
916 | __cdecl __MINGW_NOTHROW int setenv( const char *__n, const char *__v, int __f )
| ^~~~~~
查看 build/main.i 确认同一个文件被多次包含。我有标头保护并且不在我的头文件中声明任何变量。我知道没有任何问题,因为运行正常的编译命令(如下)可以工作。
gcc -Wpointer-arith -Wall -o ./bin/main.exe debug/*.h debug/*.c src/*
看看这个问题,我对发生的事情的猜测是,预处理器在被自身调用时,会将每个翻译单元的输出放入一个文件中,从而创建重复项。但是,因为正常的编译命令有效,所以我的猜测是,在调用编译器时,每个翻译单元都会调用一次预处理器,而不仅仅是预处理器本身。
所以我的问题是双重的:
- 我的猜测是否正确,或者如果它不正确,实际发生了什么?
- 如果我的猜测是正确的,你如何告诉 gcc 每个翻译单元输出一个预处理文件?
我明白我正在尝试做的不一定是“正确的”,更多的是看看什么可以做,什么不能做。
编辑
在下面的评论中查看 kaylum 的答案以获得答案。不知道我是如何错过回顾的,但事后看来是 20/20。
解决方案
推荐阅读
- integration - 超级账本和以太坊可以连接以在彼此之间传输数据或资产吗?
- cloud-foundry - 使用 binary-builder 创建自定义 Buildpack
- swift - 这是关于 swift 中优先级组的错误吗?
- javascript - Angular 单元测试:如何对 .map() 进行单元测试?
- java - 使用 JAVA 和 Itext7 将 Html 转换为 PDF 时出现 NullPointerException
- javascript - 通过 id 检索数据时无法读取未定义的属性“参数”
- dask - 如何在 Dask Dataframe 中使用 Apriori 算法?
- amazon-web-services - Logstash 输出 s3 插件不适用于 kubernetes
- php - 检查缩略图和完整图像是否在 PHP 中匹配
- elixir - 使用 Ecto 在 Elixir 的测试中有时会出现奇怪的错误