对C宏的未定义引用,但在定义它时会出现重新定义错误
Undefined reference to C Macro, but gets redefined error when I define it
我在kthread.h中定义了一个宏,如下所示。
#define KERNEL_THREAD_SAVED_KERENL_TOP_OFFSET 208
我正试图在syscall.cc 中使用该宏
#include "syscall.h"
#include "kthread.h"
#define SET_KERNEL_THREAD_TOP_OFFSET(offset, reg)
"movq " #offset "(%%" #reg "), %%rsp n"
// .. and in some function
void func() {
asm volatile(
SET_KERNEL_THREAD_TOP_OFFSET(KERNEL_THREAD_SAVED_KERNEL_TOP_OFFSET, rbx)
:::);
}
如果我编译这个,它会给出以下链接器错误。
syscall.cc:41: undefined reference to `KERNEL_THREAD_SAVED_KERNEL_TOP_OFFSET'
好的,我明白了。所以链接器可能找不到宏?所以我试着用一些不同的值在.cc中定义它。
#include "syscall.h"
#include "kthread.h"
#define KERNEL_THREAD_SAVED_KERNEL_TOP_OFFSET 100
#define SET_KERNEL_THREAD_TOP_OFFSET(offset, reg)
"movq " #offset "(%%" #reg "), %%rsp n"
然后,我得到一个编译器错误
./kernel/syscall.cc:5: error: "KERNEL_THREAD_SAVED_KERNEL_TOP_OFFSET" redefined [-Werror]
5 | #define KERNEL_THREAD_SAVED_KERNEL_TOP_OFFSET 100
|
In file included from ./kernel/syscall.cc:3:
./kernel/kthread.h:7: note: this is the location of the previous definition
7 | #define KERNEL_THREAD_SAVED_KERNEL_TOP_OFFSET 208
|
很明显,编译器知道syscall.cc中的KERNEL_THREAD_SAVED_ERNEL_TOP_OFFSET。那么为什么链接器看不到定义呢??
链接器没有业务查找宏。宏由预处理器处理,预处理器在链接器之前很久就运行了。如果链接器抱怨未定义的引用,则表示宏扩展出错。它在不该有的地方发射KERNEL_THREAD_SAVED_KERNEL_TOP_OFFSET
。
问题在于
SET_KERNEL_THREAD_TOP_OFFSET(KERNEL_THREAD_SAVED_KERNEL_TOP_OFFSET, rbx)
将扩展到
"movq " "KERNEL_THREAD_SAVED_KERNEL_TOP_OFFSET" "(%%" "rbx" "), %%rsp n"
而您希望它扩展为(使用kthread.h
中的值(
"movq " "208" "(%%" "rbx" "), %%rsp n"
之所以会发生这种情况,是因为如何处理函数类似宏的参数。当在字符串化运算符#
中使用时,它们不经历中间展开。
您可以通过引入间接层来解决此问题。
#define SET_KERNEL_THREAD_TOP_OFFSET(offset, reg)
SET_KERNEL_THREAD_TOP_OFFSET_(offset, reg)
#define SET_KERNEL_THREAD_TOP_OFFSET_(offset, reg)
"movq " #offset "(%%" #reg "), %%rsp n"
现在,当你尝试进行扩展时,它会在几个过程中扩展。首先到达
SET_KERNEL_THREAD_TOP_OFFSET_(208, rbx)
(rbx
不是宏的名称,因此它保持未标记状态(。这就变成了
"movq " "208" "(%%" "rbx" "), %%rsp n"
相关文章:
- 在类定义之后定义一个私有方法
- Android Studio:如何在build.gradle中定义自定义宏(针对不同的构建变体),并让原生C / C++
- 如何在C++中为 if 和 else 语句定义新行为
- 如何从 C++ 中的现有模板函数定义新函数
- 如何在CPropertySheet中定义新颜色
- 谁定义新操作员
- boost :: fibonacci_heap:带有比较器重新定义圆形定义错误的嵌套定义
- C 通过Typedef定义新类型
- 在 ss.clear() 之后使用 ss.str( " ") 用于新定义的字符串流
- 是标头文件中使用“新”定义的成员指针泄漏
- 使用带有Eigen库的自定义新处理程序
- 定义新的优化类型
- C# 如何定义新的指针结构
- 为模型定义新角色后程序崩溃
- C++使用类来定义新类型
- 操作员新[]定义分解
- 为什么不调用复制构造函数将临时对象复制到新定义的对象
- Qt:在按钮点击上添加自定义新选项卡
- 定义新的中缀操作符
- 错误:不能在返回类型中定义新类型