内联函数有地址吗?

19
在《C++程序设计语言》一书的第7.1.1节中,作者提到:“内联函数仍然具有独特的地址,内联函数的静态变量也是如此。”我感到困惑。如果我有一个内联函数,它就不能具有地址。这在C语言中也会发生吗?

1
我认为这个句子需要更多的上下文。"内联函数仍然有一个独特的变量"没有意义。你为什么不认为内联函数可以有一个地址呢? - CB Bailey
2
准确的引用来自于书中 - “特别地,内联函数仍然有一个唯一的地址,以及内联函数的静态变量也是如此”。这是第7.1.1节的最后一段 - 前一段以“内联指定符是编译器的提示”(我加重了)开头。静态变量在第7.1.2节中有涉及。 - user180247
@Clifford - 我正在查看特别版(第三版修改版)- 一本旧版的特别版第三版,缺少一两个附录。Stroustrup似乎从未掌握递增版本号的想法。 - user180247
@Charles,已按照指出的进行了更正。谢谢 :) - Xolve
@Steve314:...或者写清晰简洁的文本!他应该让K&R来代笔;一篇真正令人厌烦的文章对于推广语言没有什么帮助。;-) - Clifford
显示剩余2条评论
6个回答

37

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()的名称编码)。


6

如果您需要一个地址,内联函数将具有地址。标准只规定:

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


这是一个具体实现还是与“似乎”规则相关? - jww

5

没有矛盾。 在调用内联函数的部分,其代码可以进行内联处理。 在使用函数指针的部分,可以创建一个非内联版本以获取地址。


3

内联函数的扩展没有地址,但如果该函数有静态变量,则变量会具有地址。静态变量基本上只是一个全局变量,其名称仅在本地可见(即在定义它的作用域内)。内联函数中的其他变量可能会在堆栈上分配(就像它们不是内联扩展时一样)或者它们只能存在于机器寄存器中。重要的部分是它们仍然是单独的变量,并且必须像函数没有被内联扩展一样运作(与宏不同,需要极度小心,以防止多次评估引起问题)。


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

0

我认为你混淆了内联函数对象代码的位置和内联的含义。通常我们将内联函数视为在源代码级别的调用函数中放置。书中所说的是,变量名称(包括内联函数中使用静态变量)与实际上是典型的独立函数一样处理。

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接