gcc 是怎么找到 system 函数的定义(实现)的?

49 天前
 rookiemaster

程序如下:

int main()
{
    system("echo hello world");
}

使用 gcc 编译时会警告找不到 system 的声明:

DoubleHash.c: In function ‘main’:
DoubleHash.c:3:5: warning: implicit declaration of function ‘system’ [-Wimplicit-function-declaration]
    3 |     system("echo hello world");
      |     ^~~~~~

但是程序仍然可以运行,我想知道编译器是怎么找到 system 的定义的?

1606 次点击
所在节点    C
18 条回复
ho121
49 天前
应该是链接 glibc 时找到的,毕竟大部分程序都需要 glibc

我猜的。
geelaw
49 天前
system 是标准库函数,链接的时侯默认是带标准库的,所以找到了。

C 语言没有函数重载,不需要复杂的名称修饰,int system(…); 和 int system(char const *); 链接的时候去找的是同一个符号,前者是隐式声明的结果,后者是标准库的声明,故隐式声明的调用可以链接到标准库函数。
seers
49 天前
运行时候会去 ld.conf 找符号
yolee599
49 天前
int add(int a, int b) 和 float add(float a, int b, int c) 的符号是同一个,运行的时候函数会通过栈传递参数。编译的时候是通过符号来链接的,如果在头文件定义了这个函数,类型不匹配编译会出错,而如果头文件不定义,只要符号对上了编译就会成功,只会报警告。
churchmice
49 天前
推荐你看一下 link & loader
wodexinhaoleng
49 天前
问题的方向错了,这个问题你应该问这个警告是从哪来的

因为 C 语言最初的设计上,函数调用本来就是不需要声明的。只是后面的编译器保留了兼容性
proxytoworld
49 天前
你不熟悉程序编译过程,首先 gcc 会先生成.a 文件,而后进行链接,在链接的时候找到了 system ,所以能编译出来,system 在 libc 里面。如果你使用一个不存在的函数,在链接的时候找不到,就会报错了。
pagxir
49 天前
函数声明在 stdlib.h ,实现自然在 libc ,默认都会链接 libc 的。不 include stdlib 直接用 system 大概率在 64 位系统下程序崩溃
653513754
49 天前
推荐你看一下编译之后的汇编,可以清楚的看出来系统是怎么找到 system 的
ysc3839
49 天前
是 implicit-function-declaration ,直接用你给的参数类型作为定义了
rookiemaster
49 天前
@geelaw 那隐式声明与实际调用的时候参数对不上为啥编译会通过呢
leonshaw
49 天前
@rookiemaster 当作隐式函数声明 int system(); 按 ABI 调用就行了
geelaw
49 天前
@geelaw #2 更正:隐式声明是 int system();

#11 空白的参数列表的意思是没有提供参数列表信息,并没有对不上。
nuk
49 天前
隐式声明,理论上默认的函数声明会是 int f(void),但是 gcc 实际上传递了参数,而且因为 X64 是 fastcall ,前几个参数用寄存器传递,所以就算参数数量对不上,也不会崩溃。你可以试试这样,一样不会崩溃:
system("echo hello world");
system("echo hello world", "echo hello world");
cnbatch
49 天前
“隐式声明与实际调用的时候参数对不上”

不是对不上,而是因为 C 语言的特性。

在其它编程语言当中(比如 C++、Java 、C# ),int system();表示该函数不接受参数传入。

但 C 语言不同,int system(); 表示参数情况未知,是个笼统的声明。
而 int system(void) 才是其它编程语言 int system();的意思。

这里有比较详细的说明,在页面尾部 Note 那一节,句子以“Unlike in C++”开头:
https://en.cppreference.com/w/c/language/function_declaration
rookiemaster
49 天前
@cnbatch 谢谢
zeroxia
46 天前
@nuk 到底默认是 `int f()` 还是 `int f(void)`?
nuk
46 天前
@zeroxia int f(),我说错了,不指定参数类型

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

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

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

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

© 2021 V2EX