预定义宏的 __FILE__、__LINE__、__func__、stringify(#) 是如何工作的?

How do predefined macro's __FILE__, __LINE__, __func__ ,stringify(#) work?

如果我的编译器支持这些预定义的宏 (__FILE__, __LINE__, __func__),那么我可以安全地使用它们并假定它总是根据以下条件报告正确的文件和行:__FILE__, __LINE__, and __FUNCTION__ usage in C++

我还读到变量名、行号等与执行的程序集结束代码(从 .cpp 代码生成的实际 .exe 文件)无关,如果是这种情况,那么该怎么做这些宏在代码中使用时有效吗? __LINE__ 宏在汇编代码中是如何表示的?当 .exe 文件遇到 __LINE__ 宏时,它如何知道原始 .cpp 源的正确行号?

How is a LINE macro represented in assembly code?

不是。这些是 预处理器 宏。预处理器运行后,它们将被替换为文字。

例如,如果您有此代码:

void foo() {
    printf("%d", __LINE__);
}

预处理器会把它变成这样:

void foo() {
    printf("%d", 2);
}

1) "macros"像__FILE____LINE__一样被编译系统的"preprocessor".扩展了。源文本在编译器本身实际看到它之前就被修改了。

2) 对于像“__LINE__”这样的内置宏也是如此。这同样适用于您使用 #define 语句创建的任何宏。

3) "line numbers" 和 "function names" 之类的东西对调试器很重要。调试信息由编译器本身生成(不是预处理器)。它与宏扩展或汇编代码生成相关但又不同。

调试信息通常作为 "metadata".

直接保存在您的可执行文件中(连同汇编程序指令、字符串文字等)

您可以在这里阅读更多内容:"How Debuggers Work"

附录:

与调试器元数据(以上)一样,func 相似但不同。

来自 C99 标准:

6.4.2.2 预定义标识符

语义:

  1. 标识符 __func_ _ 应由翻译器隐式声明,就好像紧跟在每个函数定义的大括号之后,声明

    static const char __func__[] = "function-name";

出现了,其中函数名是词法封闭函数的名称。

  1. 这个名称被编码,就好像隐式声明已经写在源字符集中,然后被翻译成执行字符集,如翻译阶段 5 所示。

  2. 例子 考虑代码片段

    #include <stdio.h> void myfunc(void) { printf("%s\n", __func__); /* ... */ }

每次调用函数时,都会打印到标准输出流:

myfunc

您还会在许多 C 编译器中看到 __FUNCTION__,但它从来都不是标准的。

您可以在此处阅读更多内容:

__FILE__, __LINE__, and __FUNCTION__ usage in C++