使用了malloc、exit、strlen却没有 #include <stdlib.h>,有warning出现
warning: incompatible implicit declaration of built-in: function ‘strlen'
来说说这个 warning,首先你必须知道:
C90 标准允许使用一个函数时,不需要提供原型宣告,因为编译器会
假定该函数的返回型态是 int。至于堆叠平衡的需求,因为这一类函数
的堆叠是由 caller 负责清理,所以没有原型宣告,还是能正确维持平衡。
C99 不允许上述行为,C++ 也是。
gcc 比 VC 在这方面还要鸡婆,它的编译器会事先储存 C 标准函数的
原型宣告资讯,而且预设就会使用这部份资讯,除非你在编译时,使用
这个参数:
-fno-builtin
举例来说,当有以下程式码时:
#include <stdio.h>
#include <stdlib.h>
int main() {
printf("%f\n", sqrt(16.0));
return 0;
}
gcc 使用 C90 标准编译: gcc -std=c90 ss.c
会出现警告讯息:
warning: incompatible implicit declaration of built-in
function 'sqrt' [enabled by default]
printf("%f\n", sqrt(16.0));
^
意思是,在隐式宣告下,其原型资讯为 int sqrt(double);
但是这个内建函数的原型,已查出是 double sqrt (double x);
因此两者不相容 (incompatible),而 gcc 将会主动使用内建的原型宣告。
主要是警告 VC 使用者,这里不会跟 VC 一样,当成 int sqrt(double) 来用。
※ 上面的程式执行结果是:4.000000
如果改成这样编译:gcc -std=c90 -fno-builtin ss.c
则不会有警告讯息,而且程式执行结果会跟 VC 编译出来的一样,都是 0.000000。
原因并不难理解,因为 sqrt 函数把返回值放在专门存放 double 的地方,可是
编译器以为他的返回值是 int,所以跑去另一个地点取值,最后取到错误的资讯。
附带一提,如果是 C++ 编译器,会直接编译错误,如果是 C99 编译的话:
gcc -std=c99 -fno-builtin ss.c
ss.c: In function 'main':
ss.c:5:3: warning: implicit declaration of function 'sqrt'
[-Wimplicit-function-declaration]
printf("%f\n", sqrt(16.0));
^
这个错误讯息,是由于 C99 标准不想像 C90 这样,隐含的把函数返回值当成 int,
但是又不想害以前的 C90 使用者编译失败,所以只提出警告。
https://www.ptt.cc/bbs/C_and_CPP/M.1416824909.A.E7F.html
https://stackoverflow.com/questions/977233/warning-incompatible-implicit-declaration-of-built-in-function-xyz
https://stackoverflow.com/questions/11380744/i-used-pow-function-in-my-c-program-but-did-not-link-to-lm-it-still-worked-w