c++ - 对 C 宏的 undefined reference ,但在我定义它时会出现重新定义的错误

标签 c++ c macros linker c-preprocessor

我在 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_KERNEL_TOP_OFFSET。那为什么链接器看不到定义呢??

最佳答案

链接器没有业务查找宏。宏由预处理器处理,它在链接器之前运行很长时间。如果链接器提示 undefined reference ,则意味着您的宏扩展出错了。它发出 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"

关于c++ - 对 C 宏的 undefined reference ,但在我定义它时会出现重新定义的错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60360432/

相关文章:

c++ - 段错误 : C++ sort an string vector with lambda comparator

c - 如何将流 (FILE *) 与标准输出相关联?

C++定义一个接受函数并将其传递给其他函数的宏,这可能吗?

vba - 在 Excel 2010 中查找和替换而不丢失单元格格式 - 无法在包含 255 个字符的单元格上运行

c++ - std::string 的 strncpy 等价物?

c++ - C++ Excel COM自动化-Workbook.SaveAs-找不到成员

c++ - 如何使用 google test for C++ 运行数据组合

C 字符串比较 - 等于 true

c - 如何使用程序实现加载器?

c++ - C MACRO 跟踪现有源代码中的 "for"循环迭代