C 语言里面的 inline 关键字到底是啥意思?

2021-08-12 12:26:41 +08:00
 villivateur

起因是我突然发现用 GCC 不带任何编译选项来编译下面的 C 代码,会报错:

#include <stdio.h>

inline void func()
{
        printf("Hello world!\n");
}

int main()
{
        func();
        return 0;
}

错误输出:

/usr/bin/ld: /tmp/ccdw5O1b.o: in function `main':
test.c:(.text+0xe): undefined reference to `func'
collect2: error: ld returned 1 exit status

但是,用 G++ 不带任何编译选项编译下面的 C++ 代码,正常运行:

#include <iostream>

using namespace std;

inline void func()
{
        cout << "Hello world!" << endl;
}

int main()
{
        func();
        return 0;
}

我把 C 代码中的 func 加上 static 修饰符,可以正常编译:

#include <stdio.h>

static inline void func()
{
        printf("Hello world!\n");
}

int main()
{
        func();
        return 0;
}

用 inline 声明 func 也可以正常编译:

#include <stdio.h>

inline void func();

void func()
{
        printf("Hello world!\n");
}

int main()
{
        func();
        return 0;
}

编译的时候加上 -O2 选项也能正常编译。

我查了很多的博客,包括 C11 的标准文件,但是迫于理解能力,还是没能搞懂为啥会这样,所以在此请教一下大家。

附上我查的资料链接:

http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1124.pdf

https://stackoverflow.com/questions/19068705/undefined-reference-when-calling-inline-function

https://stackoverflow.com/questions/16245521/c99-inline-function-in-c-file/16245669#16245669

https://stackoverflow.com/questions/7762731/whats-the-difference-between-static-and-static-inline-function

https://runtimeverification.com/blog/undefined-c-common-mistakes/

3576 次点击
所在节点    C
17 条回复
philon
2021-08-12 13:35:44 +08:00
inline 是某个内敛函数的“**定义**”,而非“**声明**”!(这种错误主要出现在高版本的 gcc 编译器中)
简而言之,你突然在 main 里调用了一个未知的函数,所以报错了。试着在调用前将函数声明一下,比如:
```c
#include <stdio.h>

void func()
inline void func()
{
printf("Hello world!\n");
}

int main()
{
func();
return 0;
}
```
besto
2021-08-12 14:07:38 +08:00
1L 正解,另外你 Google 一下 C inline 就能得到结果了:https://stackoverflow.com/questions/31108159/what-is-the-use-of-the-inline-keyword-in-c/31108614
wangxn
2021-08-12 14:11:47 +08:00
看来 C 和 C++还是有很多细微的区别。
villivateur
2021-08-12 14:14:26 +08:00
@philon 有没有说反?是“声明”而非“定义”?
xingheng
2021-08-12 14:27:41 +08:00
内联函数,不会压栈,编译的时候会被直接展开。
villivateur
2021-08-12 14:32:54 +08:00
@xingheng 不要只看标题,麻烦看一下我的内容
fullpowers
2021-08-12 14:34:20 +08:00
C 的函数定义前需要声明,我觉得应该是这个原因
aneostart173
2021-08-12 14:56:30 +08:00
inline 在现代编译器里几乎没有任何作用。
gabon
2021-08-12 18:44:12 +08:00
是树莓派 tg 群里的吗,昨天刚好看到有人在问😂
philon
2021-08-12 19:10:06 +08:00
@villivateur 对于我这种 CET-4 都没过的人来说,想要区分`declare`和`define`还是很有挑战性的哈😂

我只是非常肤浅地以为,inline 是通知编译器要展开这段代码,但它因为没找到声明的地方就略过了,到了链接器的时候一看找不到函数原型,就抛了个`undefined reference`
sosilver
2021-08-12 20:39:11 +08:00
看 modern c 写的,
1. inline 放到函数定义上(要 inline 需要知道函数怎么实现的),一般在头文件里。
2. 默认不会生成符号(不然多次包含会被重复定义)。
3. 需要在一个 TU 里不带 inline 声明以生成符号。
(括号内只是我的理解)
dontmind
2021-08-12 23:11:59 +08:00
inline 是 c++ 先有,后来才引进 c,因为相容性问题才变了现在这样

http://www.open-std.org/jtc1/sc22/wg14/www/docs/n633.htm
>While the GCC-2.6.3 inlining facility was almost certainly modeled on the
C++ inline capability there are several differences.

....

>Much of this control is probably provided to get around the fact that the
>loader won't collapse multiple definitions of a function to a single
>instance as is done for uninitialized variables with external linkage.
Huelse
2021-08-13 01:05:16 +08:00
我一直以为的是 inline 函数会被编译进调用的位置,现代编译器会判断 inline 声明的函数实现,过于复杂的话还是像其他普通函数一样进栈地址,另外 inline 可以被声明并在头文件中实现,如有错误欢迎指正~
hobochen
2021-08-13 19:54:26 +08:00
@aneostart173 你说的几乎是指 10%以下的性能差异不算性能差异?
muzuiget
2021-08-14 19:04:33 +08:00
怎么我觉得第一个例子也应该算是合法,编译器能判断上下文吧。
hxndg
2021-08-27 12:41:57 +08:00
gcc 4.8.5 没发现这个问题
gcc 4.9.2 没发现这个问题
gcc 5.3.1 发现确实存在这个问题

然后有几个小细节需要注意下:
1 inline 是建议,不是必然展开
2 如果你把 inline 放到 main 函数后面就会报几个 warning,但是能正常编译,编译器会 implicit declaration of function ‘func’
3 inline 在前面的话,gcc -c main.c 生成的 main.o 会发现找不到 func 的定义。具体原因我就不知道了。。。
4 不要自己去给编译器的行为找合理解释。。。因为很可能解释是错的。。。。
zeroxia
2021-09-27 17:09:32 +08:00
程序员就是喜欢谁也看不起谁。本来 C 也是从 C++那边抄过来的,非又搞的和 C++不一样。
就好像理想的情况下,C++就是 C 的超集,这个世界就多简单,结果现在搞成这样。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/795313

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX