【问题标题】:Do inline functions have addresses?内联函数有地址吗?
【发布时间】:2010-07-23 12:59:16
【问题描述】:

在“The C++ Programming Language”一书的第 7.1.1 节中,作者指出:

“内联函数仍然有一个唯一的地址,内联函数的静态变量也是如此”

我很困惑。如果我有一个内联函数,那么它就没有地址。这在 C 中也会发生吗?

【问题讨论】:

  • 我认为这句话需要更多的上下文。 “内联函数仍然有一个唯一变量”没有意义。为什么你不认为内联函数可以有地址?
  • 哪个版本?我正在看第三版,看不到它在哪里说的。
  • 书中的准确引用 - “特别是,内联函数仍然具有唯一的地址,内联函数的静态变量也是如此”。这是第 7.1.1 节中的最后一件事 - 上一段以“内联说明符是编译器的 提示”开头(我的重点)。静态变量在第 7.1.2 节中介绍
  • @Clifford - 我在看特别版(修改过的第三版) - 第三版特别版的旧版,缺少一两个附录。 Stroustrup 似乎从来没有掌握增加版本号的想法。
  • @Charles,如指出的那样更正。谢谢:)

标签: c++ inline


【解决方案1】:

inline 属性只是对编译器的一个提示,它应该尝试内联你的函数。仍然可以获取函数的地址,在这种情况下,编译器还需要发出非内联版本。

例如:

#include <stdio.h>

inline void f() {
    printf("hello\n");
}

int main() {
    f();
    void (*g)() = f;
    g();
}

上面的代码打印了两次hello

我的gcc 编译器(带有-O)发出类似这样的代码:

_main:
        pushl   %ebp
        movl    %esp, %ebp
        pushl   %ebx
        subl    $20, %esp
        call    ___i686.get_pc_thunk.bx
"L00000000002$pb":
        leal    LC0-"L00000000002$pb"(%ebx), %eax
        movl    %eax, (%esp)
        call    L_puts$stub        ; inlined call to f()
        call    L__Z1fv$stub       ; function pointer call to f() (g is optimised away)
        movl    $0, %eax
        addl    $20, %esp
        popl    %ebx
        popl    %ebp
        ret

如您所见,首先调用了puts(),然后调用了L__Z1fv()(这是f() 的错误名称)。

【讨论】:

    【解决方案2】:

    如果您需要,内联函数有地址。标准只说:

    带有外部的内联函数 链接应具有相同的地址 所有翻译单元。

    【讨论】:

    • 这是一个体现还是与“as if”规则有关?
    【解决方案3】:

    没有矛盾。 在调用内联函数的部分,可以内联其代码。 在您使用函数指针的部分,可以创建非内联版本以具有地址。

    【讨论】:

      【解决方案4】:

      函数的内联扩展没有地址,但如果该函数有静态变量,则该变量确实有地址。静态变量基本上只是一个全局变量,其 name 仅在本地可见(即,在定义它的范围内)。内联函数中的其他变量可能会分配在堆栈上(就像它们没有内联扩展时一样),或者它们可能只是存在于机器寄存器中。重要的部分是它们仍然是单独的变量,并且必须像函数根本没有内联扩展一样行事(例如,与宏不同,宏需要特别小心以防止多次评估导致问题)。

      【讨论】:

        【解决方案5】:

        它们可能在某些调用站点被内联,但它们仍然作为地址空间中的正常函数存在。

        【讨论】:

          【解决方案6】:

          我认为您将内联函数对象代码的位置与内联的含义混淆了。通常,我们将内联函数可视化为位于源代码级别的调用函数中。这本书的意思是,变量名称,包括在内联函数中使用静态,被视为与该函数实际上是典型的独立函数一样。

          此外,使用 inline 关键字处理函数并不能保证它们会被内联,并且对于不能内联的情况(例如需要地址时),将生成非内联版本。

          【讨论】:

            猜你喜欢
            • 2013-09-22
            • 1970-01-01
            • 2020-04-28
            • 1970-01-01
            • 2011-12-11
            • 2017-10-26
            • 2014-01-03
            • 2014-02-23
            • 1970-01-01
            相关资源
            最近更新 更多