预定义宏的__FILE __,_ _ _ _ _,_ _ func __,字符串化(#)如何工作?

时间:2015-09-03 15:12:51

标签: c++ macros

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

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

2 个答案:

答案 0 :(得分:9)

  

如何在汇编代码中表示 LINE 宏?

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

例如,如果您有此代码:

function (a, b) {
    return a.rating.localeCompare(b.rating) ||
           a.tolPercents - b.tolPercents ||
           a.size - b.size;
}

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

var data = [
        "size64_tolPercent0.01_best",
        "size256_tolPercent0.01_best",
        "size256_tolPercent0_worst",
        "sizemax_tolPercent0_worst",
        "size1518_tolPercent0_worst",
        "size64_tolPercent0.01_worst",
        "size512_tolPercent0.01_worst",
        "size1518_tolPercent0.01_worst",
        "size256_tolPercent0_best"
    ],
    result = data.map(function (el, i) {
        var a = /^size(.+)_tolpercent(.+)_(.+)$/i.exec(el);
        return {
            index: i,
            rating: a[3],
            tolPercents: a[2],
            size: a[1] === 'max' ? Number.MAX_VALUE : a[1]
        };
    }).sort(function (a, b) {
        return a.rating.localeCompare(b.rating) || a.tolPercents - b.tolPercents || a.size - b.size;
    }).map(function (el) {
        return data[el.index];
    });

document.write('<pre>' + JSON.stringify(result, 0, 4) + '</pre>');

答案 1 :(得分:3)

1)编译系统的"preprocessor".扩展了像__FILE____LINE__这样的“宏”。在编译器本身实际看到之前修改源文本。

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

3)“行号”和“函数名称”之类的东西对调试器很重要。调试信息由编译器本身(而不是预处理器)生成。它与宏扩展或汇编代码生成有关 - 但不同。

调试信息通常直接保存在可执行文件中(连同汇编指令,字符串文字等)作为“元数据”。

您可以在此处阅读更多内容:"How Debuggers Work"

附录:

与调试器元数据(上图)类似, func 类似 - 但不同。

来自C99标准:

6.4.2.2预定义标识符

语义:

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

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

  2. 出现了,其中function-name是词法封闭函数的名称。

    1. 此名称的编码就好像隐式声明已写入源字符集,然后转换为执行字符集,如转换阶段5所示。

    2. 实施例 考虑代码片段

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

    3. 每次调用该函数时,它都将打印到标准输出流:

      myfunc

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

      您可以在这里阅读更多内容:

      __FILE__, __LINE__, and __FUNCTION__ usage in C++