[置顶] 泰晓 RISC-V 实验箱,配套 30+ 讲嵌入式 Linux 系统开发公开课
[c-faq] 1.25-隐式函数声明
by PingboWen of TinyLab.org 2013/08/24
在 C 语言中,隐式函数声明是指函数在调用之前没有明确的声明或定义。 不同的编译器对待隐式函数声明的方式不同。在 GCC 中,编译器只会给出一个警告,但是只要不和默认函数原型冲突,编译器是不会报错的。 下面来看一个实验:
test.c:
#include <stdio.h>
int f1()
{
return f2();
}
int f2(int i)
{
return 1;
}
int main(int argc, char * argv[])
{
printf("%d\n",f1());
return 0;
}
当你直接用 gcc test.c 的方式编译这个程序的时候,编译器是不会报错的,并且能够正常通过编译。
但是当你把上面的 f2 函数的返回类型改为 char 后,还是按照原先的方式编译(gcc test.c),你会发现,编译器会报错,提示在 f2 定义的那个地方和函数 f2 类型冲突。
怎么会出现类型冲突的错误?我之前有定义 f2 么?
其实这中间就是隐式函数声明在捣鬼。在 gcc 中,如果编译器碰到一个未声明的函数调用,编译器默认会把这个函数的原型当作 int f()
。也就是说这个函数可以接受任意的参数,并且返回一个整型数。这也是为什么第一次编译的时候,编译器是可以通过编译的,并且程序运行正常。因为下面的 f2 定义刚好和默认的函数原型兼容。
但是,如果我们把返回类型换成 char 之后,这就和前面的函数原型不兼容了。就相当于同一个文件中出现两个对同一个名字的不同的函数声明,这在 C 语言中,当然是不允许的,所以编译器会报错:类型冲突。
在 C89 的规范中,是允许这种隐式函数声明,且 gcc 默认是按照 c89 的标准来编译程序的,这也是为什么 gcc 在第一次编译的时候,连一个警告都不出,其实你可以加一个 -Wall
的参数, gcc 就会出现警告:隐式函数声明。
在 C99 的规范,已经不允许隐式函数声明了。所以如果你在用 gcc 编译的时候,加上 -std=c99
的时候,编译器马上会出现一个警告:隐式函数声明。如果你再加上一个 -Werror
的选项的话,那就直接出现错误了。
从这也可以看出,不同的标准之间的差异。以后编译程序的时候,还是尽量加上 -Wall -std=c99
,可以发现很多隐藏的错误。
猜你喜欢:
- 我要投稿:发表原创技术文章,收获福利、挚友与行业影响力
- 知识星球:独家 Linux 实战经验与技巧,订阅「Linux知识星球」
- 视频频道:泰晓学院,B 站,发布各类 Linux 视频课
- 开源小店:欢迎光临泰晓科技自营店,购物支持泰晓原创
- 技术交流:Linux 用户技术交流微信群,联系微信号:tinylab
支付宝打赏 ¥9.68元 | 微信打赏 ¥1.00元 | |
请作者喝杯咖啡吧 |
Read Album:
- [c-faq] 6.11-数组怪异写法
- [c-faq] 3.8-未定义行为与sequence point
- [c-faq] 3.16-左值和右值
- [c-faq] 2.14, 2.15-offsetof和struct成员异类访问
- [c-faq] 2.10-designated initializer