在学习C语言函数的时候,老师总会告诉我们函数要写声明,然后再定义。这是个稳健的做法。等我自己学习了其他高级语言以后,回头再来写C,突然就觉得函数要写声明有点麻烦。无意间发现有一次函数没写声明居然编译(GCC 5.3)也通过了,而且都没有报错。于是想起来要好好研究一下这个C语言的函数声明什么时候可以不写,什么时候必须写。

这其实谈不上是技术性问题。就好像讨论i++ 和++i那么无聊。这都是编译器导致的语法问题。说他们都是历史遗留问题都不为过。

但是在C语言学习过程中,你不得不去把这些鬼问题弄清楚。这样在以后面对千奇百怪的C语言代码的时候才能做到内心毫无波动。

有的书上是这么说的,如果函数定义放在main函数前面,可以不用写声明。如果函数放在main函数后面,就规定要写函数声明。这么说没毛病。不过我自己又无聊地尝试了一下,发现了更准确的规则。如果在函数定义在这个函数调用之前,就不需要写声明。否则就要写声明。

关于这个函数定义的位置其实也是个可以摸索的事情。C语言不允许在一个函数中定义其他函数,但是main函数除外。我发现可以在main函数中定义函数。如果你在main函数中定义函数,如果在函数被调用之前就定义了这个函数,那么就不需要声明了,这样编译连警告都没有,如果你在main函数中定义函数,而函数定义的位置比函数调用还要后,那么就无法通过编译了。进一步做无聊事情,假设我们在函数调用语句之后再定义函数,这个条件下有两种情况(单文件下),在main函数外面定义这个函数,编译会出警告信息,但是可以通过。如果是在main函数里面定义的。那就编译就会有警告+错误信息。

同样的关于函数声明的位置也是可以无聊地摸索一下。因为函数声明可以放在main函数外面,也可以放在main函数里面。我说可以放在main函数外面肯定说的是放在main函数上面。这个是正常做法。有的书会把声明放在main函数里面,也是可以的。只要只要声明函数的位置在函数调用前面就OK了。由此可以弱弱地推测出,C编译器是看到了声明,然后去寻找对应函数定义进行编译。如果没有声明,但是函数定义写在函数调用前面,那这个函数定义也比函数调用的代码先一步编译了也没问题了。这个弱弱地推测,就可以解释我以上无聊的实验结果了。

当时除了我这样无聊的初学者,谁会一直在main函数里写函数呢?

C语言函数声明什么时候可以省略,什么时候不能省?的更多相关文章

  1. 05. Go 语言函数

    Go 语言函数 函数是组织好的.可重复使用的.用来实现单一或相关联功能的代码段,其可以提高应用的模块性和代码的重复利用率. Go 语言支持普通函数.匿名函数和闭包,从设计上对函数进行了优化和改进,让函 ...

  2. C语言中函数声明实现的位置

    在学习C语言的时候我遇到了这么个事情,因为之前先学习的C#,在C#编译器中,函数的声明位置不会影响编译的结果,但是在C语言中却发生了错误 先看一段代码: #include <stdio.h> ...

  3. C语言函数的声明以及函数原型

    C语言代码由上到下依次执行,原则上函数定义要出现在函数调用之前,否则就会报错.但在实际开发中,经常会在函数定义之前使用它们,这个时候就需要提前声明.所谓声明(Declaration),就是告诉编译器我 ...

  4. c语言中的隐式函数声明(转)

    本文转自:http://www.jb51.net/article/78212.htm 在c语言里面开来还是要学习c++的编程习惯,使用函数之前一定要声明.不然,即使编译能通过,运行时也可能会出一些莫名 ...

  5. 万恶之源:C语言中的隐式函数声明

    1 什么是C语言的隐式函数声明 在C语言中,函数在调用前不一定非要声明.如果没有声明,那么编译器会自己主动依照一种隐式声明的规则,为调用函数的C代码产生汇编代码.以下是一个样例: int main(i ...

  6. C语言的函数声明,定义,调用以及exit退出

    #include <stdio.h> #include <stdlib.h> void singing(); int main() { singing(); system(&q ...

  7. C与C++的函数声明中省略参数的不同意义

    一直都以为C/C++中形如 int func(); 这样的函数声明其意义就是一个参数 void(没有参数)的函数.然而今天在看C++的时候突然看到这么一句: 对于带空参数表的函数,C和C++有很大的不 ...

  8. C语言的“隐式函数声明”违背了 “前置声明” 原则

    这个问题来源于小组交流群里的一个问题: 最终问题落脚在 : 一个函数在main中调用了,必须在main之前定义或者声明吗? 我在自己的Centos上做了实验,结果是函数不需要,但是结构体(变量也要)需 ...

  9. C语言中函数声明、形参、实参

    函数原型: 原型prototype是函数的声明:描述了函数的返回值与参数: 函数原型说明了两点: 1.该函数的返回值 2.该函数的参数及其类型 ++++++++++++++++++++++++++++ ...

随机推荐

  1. PHP、mySQL及Navicat安装·Mac

    PHP配置 Mac系统对开发人员非常友好,除了自带Apache外,还带有能与Apache相匹配的服务器端脚本语言PHP,因此,Mac中PHP的启动只需要在Apache服务中进行一下超级简单的配置即可直 ...

  2. 重谈react优势——react技术栈回顾

    react刚刚推出的时候,讲react优势搜索结果是几十页. 现在,react已经慢慢退火,该用用react技术栈的已经使用上,填过多少坑,加过多少班,血泪控诉也不下千文. 今天,再谈一遍react优 ...

  3. Python实现图像直方图均衡化算法

    title: "Python实现图像直方图均衡化算法" date: 2018-06-12T17:10:48+08:00 tags: [""] categorie ...

  4. CentOS 7 配置DHCP

    DHCP(Dynamic Host Configuration Protocol,动态主机配置协议)是一个局域网的网络协议,使用UDP协议工作, 主要有两个用途:给内部网络或网络服务供应商自动分配IP ...

  5. 实现一个自定义的ArrayList类,实现将原List中的每个数据都乘以10

    1.首先自定义一个Operate接口,如下所示: public interface Operate { public Integer caozuo(Integer i); } 2.实现自定义的Arra ...

  6. 小程序如何封装自定义组件(Toast)

    1.创建和pages 同级的component目录新建一个myToast目录 例如: 2.myToast.wxml文件内容: <!-- 自定义toast组件 --> <!-- nam ...

  7. tomcat1(servlet,http,socket)

    1.servlet容器是如何工作的? a.创建一个request对象,用可能会在调用的Servlet中使用到的信息填充该request对象(参数,头,cookies,查询字符串,URI等).reque ...

  8. 谷歌浏览器导出excel失败问题解决(网上都没解决)

    java poi导出excel报了网络错误,信息已经写回到chrome浏览器(IE/FF均无此问题).如下所示: 从chrome的network大小部分也可以看出是正确的. 网上很多答案说将file. ...

  9. 20175312 2018-2019-2 《Java程序设计》第8周学习总结

    20175312 2018-2019-2 <Java程序设计>第8周学习总结 教材学习内容总结 已依照蓝墨云班课的要求完成了第十章的学习,主要的学习渠道是PPT,和书的课后习题. 总结如下 ...

  10. hdu2844 Coins -----多重背包+二进制优化

    题目意思:给出你n种硬币的面额和数量,询问它能够组合成1~m元中的几种情况. 这题如果直接按照完全背包来写的话,会因为每一种硬币的数目1 ≤ Ci ≤ 1000而超时,所以这里需要运用二进制优化来解决 ...