【问题标题】:C: Pointer to inline functionC:指向内联函数的指针
【发布时间】:2012-02-11 17:28:19
【问题描述】:

我在 H 文件中定义了一个 static inline 函数,并且在 C 文件中的某个位置,我为该函数分配了一个指针,如下所示:

foo.h:

static inline void frobnicate(void) {
    // frobs something.
}

foo.c

#include "foo.h"

void execute(void (*func)(void) ) {
    func();
}

void blahBlahBlah(void) {
    execute(frobnicate);
}

bar.c

#include "foo.h"
// ...
frobnicate();

所以我认为这里会发生的是编译器将从 bar.c 内联对 frobnicate 的调用,但在 foo.c 中,它实际上必须创建一个函数来实现 frobnicate,以便它可以有一个工作指针。

谁能确认我的理解是否准确,否则纠正我?

【问题讨论】:

  • 可以通过阅读生成的代码来确认。我不认为这个 必须 有特定的工作方式。如果编译器说“有人想要这个地址,那么我们不要内联它”,我不会感到惊讶。
  • 记住inline只是对编译器的一个建议
  • 它也可以推断它可以简单地将frobnicate 直接内联到blahBlahBlah 并跳过中间人。没有指向frobnicate 的指针以允许它从另一个翻译单元使用的方式存储,因此frobnicate 不需要存在于程序集输出中。

标签: c function-pointers inline-functions


【解决方案1】:

inline 是 C 标准的用词不当之一。它的主要含义是能够将函数的定义放在头文件中,而不必在链接时处理“多重定义”的问题。

在 C99 和 C11 中实现您想要实现的官方方法是在头文件中定义 inline,而不使用 static。由于您还需要发出符号,因此您需要告诉编译器这应该是哪个编译单元。这种实例化可以通过在该 .c 文件中添加一个 声明 来完成,您可以在其中省略 inline 关键字。

最自然地,您可以在实际需要符号的地方使用 .c 文件。

【讨论】:

  • 如果内联定义在没有static的头文件中,那么我尝试链接时不会有多个同名定义(内联函数)吗?
  • 你会遇到联动问题。要么让它static inline,冒着多重定义的风险,要么放弃内联。您还可以创建一个包装器,它将位于 C 文件中并且不会内联,并获取指向它的指针(不会影响性能,因为真正的函数将内联到包装器中)。
  • @bmearns,使用符合 C99 的编译器,您将不会遇到链接问题。这正是inline 关键字的含义。 gustedt.wordpress.com/2010/11/29/…
  • @Jens:谢谢,那个链接澄清了很多。我不太清楚编译器是如何处理它的,但我想我知道如何应用它。
【解决方案2】:

是的,你是对的。当您将指针指向函数时,编译器必须创建一个“独立”版本,其中代码可以作为普通函数调用。

内联函数的好处是不需要创建调用代码,并且可以应用任何其他优化来集成调用函数和内联函数。但是当您需要对函数进行常规调用时(例如当您获取地址来调用它时),这些优化就不再可能了。

【讨论】:

  • 这对许多编译器来说可能是正确的,但我无法想象为什么需要编译器这样做。即使在函数指针的情况下,OP 的示例也可以很容易地内联。
  • inline 是建议。如果编译器不能内联,它不会,如果不能,它可能仍然决定不内联(即使没有inline 关键字它也可能内联)。函数指针通常会阻止内联,但在这种情况下编译器可能会发现它们不会(或者它可能不会打扰)。
  • 是的,在这种情况下可以内联函数。我认为这是问题的简化版本。但你是对的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多