C 内联函数和“未定义的外部”函数错误
我试图用内联函数替换一些宏子例程,以便编译器可以优化它们,以便调试器可以单步执行它们,等等。如果我将它们定义为普通函数,它可以工作:
void do_something(void)
{
blah;
}
void main(void)
{
do_something();
}
但如果我将它们定义为内联:
inline void do_something(void)
{
blah;
}
void main(void)
{
do_something();
}
它说“错误:未定义的外部”。这意味着什么?我在黑暗中尝试了一下
static inline void do_something(void)
{
blah;
}
void main(void)
{
do_something();
}
,没有再出现错误。函数定义和函数调用位于同一个 .c 文件中。
有人可以解释为什么一个有效而另一个无效吗?
(第二个相关问题:如果我想在多个 .c 文件中使用内联函数,我应该将它们放在哪里?)
I'm trying to replace some macro subroutines with inline functions, so the compiler can optimize them, so the debugger can step into them, etc. If I define them as normal functions it works:
void do_something(void)
{
blah;
}
void main(void)
{
do_something();
}
but if I define them as inline:
inline void do_something(void)
{
blah;
}
void main(void)
{
do_something();
}
it says "Error: Undefined external". What does that mean? Taking a stab in the dark, I tried
static inline void do_something(void)
{
blah;
}
void main(void)
{
do_something();
}
and no more errors. The function definition and call to the function are in the same .c file.
Can someone explain why one works and the other doesn't?
(Second related question: Where do I put inline functions if I want to use them in more than one .c file?)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
首先,编译器并不总是将内联函数标记为
inline
;例如,如果您关闭所有优化,它可能不会内联它们。当您定义内联函数
并使用该函数时,即使在同一文件中,对该函数的调用也是由链接器而不是编译器解析的,因为它是隐式“外部”的。但这个定义本身并不提供函数的外部定义。
如果您在可以看到
inline
定义的 C 文件中包含不带inline
的声明,则编译器将提供该函数的外部定义,并且错误应该消失。
静态内联起作用的原因是它使函数仅在该编译单元内可见,因此允许编译器解析对函数的调用(并优化它)并发出内部函数的代码那个编译单元。然后链接器不必解析它,因此不需要外部定义。
放置内联函数的最佳位置是在头文件中,并声明它们
静态内联
。这消除了对外部定义的任何需要,因此解决了链接器问题。但是,这会导致编译器在使用该函数的每个编译单元中发出该函数的代码,因此可能会导致代码膨胀。但由于该函数是内联的,因此它可能很小,因此这通常不是问题。另一种选择是在标头中将其
定义为
extern inline
,并在一个 C 文件中提供extern
声明 没有inline
修饰符。gcc 手册是这样解释的:
First, the compiler does not always inline functions marked as
inline
; eg if you turn all optimizations off it will probably not inline them.When you define an inline function
and use that function, even in the same file, the call to that function is resolved by the linker not the compiler, because it is implicitely "extern". But this definition alone does not provide an external definition of the function.
If you include a declaration without
inline
in a C file which can see the
inline
definition, the compiler will provide an external definition of the function, and the error should go away.The reason
static inline
works is that it makes the function visible only within that compilatioin unit, and so allows the compiler to resolve the call to the function (and optimize it) and emit the code for the function within that compilation unit. The linker then doesn't have to resolve it, so there is no need for an external definition.The best place to put inline function is in a header file, and declare them
static inline
. This removes any need for an external definition, so it resolves the linker problem. However, this causes the compiler to emit the code for the function in every compilation unit that uses it, so could result in code bloat. But since the function is inline, it is probably small anyway, so this usually isn't a problem.The other option is to define it as
extern inline
in the header, and in one C file provide andextern
declaration without theinline
modifier.The gcc manual explains it thus:
对于要与 C99 一起使用的内联函数(它们只进入该语言),您必须在头文件
和一个编译单元(又名 . c) 您放置某种
没有
内联
的“实例化”。For
inline
functions to work with C99 (they only came there into the language) you'd have to give the definition in a header fileand in one compilation unit (aka .c) you place some sort of "instantiation"
without the
inline
.如果您想从多个文件中使用它们,则必须将它们放入头文件中。
对于链接器错误:函数的默认声明意味着它是“外部”的,但由于它是内联的,链接器可以找到编译器生成的符号存根,因此会出现错误。
You have to put them in a header file if you want to use them from multiple files.
And for the linker error: the default declaration of a function implies that it's "extern", but since it's inlined, the linker can find the compiler-generated symbol stub, hence the error.