C语言函数声明什么时候可以省略,什么时候不能省?
在学习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语言函数声明什么时候可以省略,什么时候不能省?的更多相关文章
- 05. Go 语言函数
Go 语言函数 函数是组织好的.可重复使用的.用来实现单一或相关联功能的代码段,其可以提高应用的模块性和代码的重复利用率. Go 语言支持普通函数.匿名函数和闭包,从设计上对函数进行了优化和改进,让函 ...
- C语言中函数声明实现的位置
在学习C语言的时候我遇到了这么个事情,因为之前先学习的C#,在C#编译器中,函数的声明位置不会影响编译的结果,但是在C语言中却发生了错误 先看一段代码: #include <stdio.h> ...
- C语言函数的声明以及函数原型
C语言代码由上到下依次执行,原则上函数定义要出现在函数调用之前,否则就会报错.但在实际开发中,经常会在函数定义之前使用它们,这个时候就需要提前声明.所谓声明(Declaration),就是告诉编译器我 ...
- c语言中的隐式函数声明(转)
本文转自:http://www.jb51.net/article/78212.htm 在c语言里面开来还是要学习c++的编程习惯,使用函数之前一定要声明.不然,即使编译能通过,运行时也可能会出一些莫名 ...
- 万恶之源:C语言中的隐式函数声明
1 什么是C语言的隐式函数声明 在C语言中,函数在调用前不一定非要声明.如果没有声明,那么编译器会自己主动依照一种隐式声明的规则,为调用函数的C代码产生汇编代码.以下是一个样例: int main(i ...
- C语言的函数声明,定义,调用以及exit退出
#include <stdio.h> #include <stdlib.h> void singing(); int main() { singing(); system(&q ...
- C与C++的函数声明中省略参数的不同意义
一直都以为C/C++中形如 int func(); 这样的函数声明其意义就是一个参数 void(没有参数)的函数.然而今天在看C++的时候突然看到这么一句: 对于带空参数表的函数,C和C++有很大的不 ...
- C语言的“隐式函数声明”违背了 “前置声明” 原则
这个问题来源于小组交流群里的一个问题: 最终问题落脚在 : 一个函数在main中调用了,必须在main之前定义或者声明吗? 我在自己的Centos上做了实验,结果是函数不需要,但是结构体(变量也要)需 ...
- C语言中函数声明、形参、实参
函数原型: 原型prototype是函数的声明:描述了函数的返回值与参数: 函数原型说明了两点: 1.该函数的返回值 2.该函数的参数及其类型 ++++++++++++++++++++++++++++ ...
随机推荐
- nuget包管理nuget服务器发布包时出现请求报错 406 (Not Acceptable)
在window服务器上部署nuget服务器时,发布包时出现请求报错 406 (Not Acceptable) 验证用户名.密码正确的情况下,还是出现上面错误.后面跟踪服务器日志,发现window\te ...
- day1:java学习第一天之eclipse安装
选择开发语言的学习其实不用纠结,如果你说自己是做开发的,连最流行的开发语言都不会,好像说不过去,并且最流行也说明用的人多,优秀的人也会,自己要提高要多向优秀的人学习.想明白这点其实选择就好说了,再一个 ...
- GDI和内核对象区别
1.GDI对象和核心对象之间最主要的区别在于GDI对象有单一拥有者,不是进程就是线程 2.核心对象可以有一个以上的拥有者,甚至可以跨进程,为了保持对每一位(拥有者)的追踪,核心对象保持了一个引用计数, ...
- Linux环境上部署Flask
[该文章只涉及个人部署的简单流程,读者可通过其它途径了解详细部署流程] 依个人部署项目可预先安装好需要的环境,这里已提前安装好LNMP环境 1.安装Python环境 安装virtualenv环境 配置 ...
- Elasticsearch从入门到精通之Elasticsearch集群内的原理
上一章节我介绍了Elasticsearch安装与运行,本章节及后续章节将全方位介绍 Elasticsearch 的工作原理 在这个章节中,我将会再进一步介绍 cluster . node . shar ...
- sitecore 获取item的URL
给出一个简单的sitecore项: Item item; 该项目本身不包含它的网址.要获取项目的URL,您需要调用static类Sitecore.Links.LinkManager string ur ...
- Django model 字段类型及选项解析---转载
model field 类型1.AutoField() 自增的IntegerField,通常不用自己设置,若没有设置主键,Django会自动添加它为主键字段,Django会自动给每张表添加一个自增的p ...
- Python的伪造数据生成器:Faker
我们在开发中常常需要利用一些假数据来做测试,这种时候就可以使用 Faker 来伪造数据从而用来测试. Faker 是一个可以让你生成伪造数据的Python包.当你需要初始化数据库,创建美观的XML文档 ...
- Linux系统下为普通用户加sudo权限
Linux下为普通账号加sudo权限 1. 错误提示:当我们使用sudo命令切换用户的时候可能会遇到提示以下错误:xxx is not in the sudoers file. This incide ...
- QT4.8应用控制程序设计
2012-02-20 22:06:59 从uboot到kernel最新版最后到QT最新版移植都完成后,从初级阶段要走向中级阶段了.初步一个设想是然2440通过QT界面控制小车.先做一个界面模块控制LE ...