※ 引述《k03004748549 (蚬)》之铭言:
: 开发平台(Platform): (Ex: VC++, GCC, Linux, ...)
: GCC (Ubuntu 4.8.2-19ubuntu1)
: 额外使用到的函数库(Library Used): (Ex: OpenGL, ...)
: 只有 -lm
: 问题(Question):
: 大家好...我最近才刚接触C
: 这边问的感觉应该是小问题,不过google都查不到...
: 还请各位鞭小力点
: 最近在看一段code,其年代久远(约1990)
: 可能是规范与现今有差异,或是当时平台不同(好像最早是在sparc上run的)
: code里面常有一些疏漏
: 例如:
略
: 2. 使用了malloc、exit、strlen却没有 #include <stdlib.h>
: 同样的有warning出现
: warning: incompatible implicit declaration of built-in
: function ‘strlen’ [enabled by default]
: 这边我也是很好奇不去include到底compiler会做什么事
: 因为程式仍然可以执行,而且某些程式(很少,大约一两个)
: 在我 #include <stdlib.h>之后
: 反而会出现 segmentation fault,让我感到很疑惑
: 还烦请各位指点迷津,谢谢
猜不到怎么出现 segmentation fault 的,
先提供引起这个错误的那一段程式码再看看吧。
来说说这个 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 使用者编译失败,所以只提出警告。