程序如下:
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 的定义的?
1
ho121 248 天前
应该是链接 glibc 时找到的,毕竟大部分程序都需要 glibc
我猜的。 |
2
geelaw 248 天前 via iPhone 2
system 是标准库函数,链接的时侯默认是带标准库的,所以找到了。
C 语言没有函数重载,不需要复杂的名称修饰,int system(…); 和 int system(char const *); 链接的时候去找的是同一个符号,前者是隐式声明的结果,后者是标准库的声明,故隐式声明的调用可以链接到标准库函数。 |
3
seers 248 天前 via Android
运行时候会去 ld.conf 找符号
|
4
yolee599 248 天前 1
int add(int a, int b) 和 float add(float a, int b, int c) 的符号是同一个,运行的时候函数会通过栈传递参数。编译的时候是通过符号来链接的,如果在头文件定义了这个函数,类型不匹配编译会出错,而如果头文件不定义,只要符号对上了编译就会成功,只会报警告。
|
5
churchmice 248 天前
推荐你看一下 link & loader
|
6
wodexinhaoleng 248 天前 1
问题的方向错了,这个问题你应该问这个警告是从哪来的
因为 C 语言最初的设计上,函数调用本来就是不需要声明的。只是后面的编译器保留了兼容性 |
7
proxytoworld 248 天前
你不熟悉程序编译过程,首先 gcc 会先生成.a 文件,而后进行链接,在链接的时候找到了 system ,所以能编译出来,system 在 libc 里面。如果你使用一个不存在的函数,在链接的时候找不到,就会报错了。
|
8
pagxir 248 天前 via Android
函数声明在 stdlib.h ,实现自然在 libc ,默认都会链接 libc 的。不 include stdlib 直接用 system 大概率在 64 位系统下程序崩溃
|
9
653513754 248 天前
推荐你看一下编译之后的汇编,可以清楚的看出来系统是怎么找到 system 的
|
10
ysc3839 248 天前 via Android
是 implicit-function-declaration ,直接用你给的参数类型作为定义了
|
11
rookiemaster OP @geelaw 那隐式声明与实际调用的时候参数对不上为啥编译会通过呢
|
12
leonshaw 248 天前
@rookiemaster 当作隐式函数声明 int system(); 按 ABI 调用就行了
|
14
nuk 248 天前
隐式声明,理论上默认的函数声明会是 int f(void),但是 gcc 实际上传递了参数,而且因为 X64 是 fastcall ,前几个参数用寄存器传递,所以就算参数数量对不上,也不会崩溃。你可以试试这样,一样不会崩溃:
system("echo hello world"); system("echo hello world", "echo hello world"); |
15
cnbatch 248 天前
“隐式声明与实际调用的时候参数对不上”
不是对不上,而是因为 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 |
16
rookiemaster OP @cnbatch 谢谢
|
19
chisato 134 天前
#include <assert.h>
#include <ctype.h> #include <errno.h> #include <float.h> #include <limits.h> #include <stdarg.h> #include <stdbool.h> #include <stddef.h> #include <stdint.h> #include <stdio.h> #include <stdlib.h> #include <string.h> |