Edg*_*jān 4 c linkage function-declaration implicit-declaration
最近我学会了C中的隐式函数声明.主要观点很明确,但我对在这种情况下理解链接过程有些麻烦.
请考虑以下代码(文件ac):
#include <stdio.h>
int main() {
double someValue = f();
printf("%f\n", someValue);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
如果我尝试编译它:
gcc -c a.c -std=c99
Run Code Online (Sandbox Code Playgroud)
我看到关于隐式声明功能的警告f().
如果我尝试编译和链接:
gcc a.c -std=c99
Run Code Online (Sandbox Code Playgroud)
我有一个未定义的引用错误.一切都很好.
然后我添加另一个文件(文件bc):
double f(double x) {
return x;
}
Run Code Online (Sandbox Code Playgroud)
并调用下一个命令:
gcc a.c b.c -std=c99
Run Code Online (Sandbox Code Playgroud)
令人惊讶的是,一切都成功连接 当然在./a.out调用后我看到了垃圾输出.
所以,我的问题是:如何将隐式声明函数的程序链接起来?在编译器/链接器的引擎下我的例子会发生什么?
首先,因为C99,从标准中删除了函数的隐式声明.编译器可能支持编译遗留代码,但这并不是强制性的.引用标准前言,
- 删除隐式函数声明
这就是说,按照C11章节§6.5.2.2
如果使用不包含原型的类型定义函数,并且促销后的参数类型与促销后的参数类型不兼容,则行为未定义.
所以,在你的情况下,
函数调用本身是隐式声明(从C99开始变为非标准),
并且由于函数签名不匹配[ 假定函数的隐式声明具有int返回类型 ],您的代码将调用未定义的行为.
只是为了添加更多的引用,如果在调用后尝试在同一个编译单元中定义函数,由于不匹配签名,您将收到编译错误.
但是,您的函数是在单独的编译单元中定义的(并且缺少原型声明),编译器无法检查签名.编译之后,链接器获取目标文件,并且由于链接器中没有任何类型检查(并且目标文件中也没有信息),请愉快地链接它们.最后,它将成功完成编译和链接以及 UB.