2012-01-16 200 views
10

我有在H文件中定义的static inline功能,并在一个C文件中的一个点,我指定一个函数指针,是这样的: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,以便它可以工作指向它的指针。

任何人都可以确认我的理解是否准确,否则纠正我?

+2

*您可以通过阅读生成的代码进行确认。我不认为这个*具有特定的工作方式。如果编译器“有人想要这个地址,那么我们就不要内联”。 – unwind 2012-01-16 20:10:03

+7

请记住,'inline'对于编译器来说只是一个_suggestion_。 – 2012-01-16 20:10:23

回答

10

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

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

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

+0

如果内联定义位于不带'static'的头文件中,那么当我尝试链接时,是否会出现同名多个定义(内联函数)? – brianmearns 2012-01-16 20:29:44

+0

您将遇到链接问题。要么使其成为“静态内联”,并冒着多种定义的风险,或者放弃内联。你也可以创建一个包装器,它将在一个C文件中,并且不会内联,并且指向它(不会影响性能,因为真正的函数将被内联到包装器中)。 – ugoren 2012-01-16 21:38:07

+0

@bmearns,与C99兼容的编译器,你将没有联系问题。这正是'inline'关键字的意义。 http://gustedt.wordpress.com/2010/11/29/myth-and-reality-about-inline-in-c99/ – 2012-01-17 10:48:01

7

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

内联函数的好处是不需要创建调用代码,并且可以使用任何其他优化来集成调用者函数和内联函数。但是当你需要定期调用函数时(就像你用地址来调用它),那些优化是不可能的。

+2

对许多编译器来说,这可能是正确的,但我不能想象为什么需要编译器来这样做。即使在函数指针的情况下,OP的例子也可以很容易地内联。 – 2012-01-16 20:31:26

+0

'inline'是一个建议。如果编译器不能内联,它不会,如果不能,它可能仍然决定不要(即使没有'inline'关键字,它也可能内联)。函数指针通常可以防止内联,但在这种情况下,编译器可能会发现它们不会(或者不会打扰)。 – ugoren 2012-01-16 21:35:11

+0

是的,在这种情况下,可以内联该功能。我认为这是该问题的简化版本。但你是对的。 – Governa 2012-01-17 13:06:53