c语言函数定义、函数声明、函数调用以及extern跨文件的变量引用
1、如果没有定义,只有声明和调用:编译时会报连接错误。undefined reference to `func_in_a'
2、如果没有声明,只有定义和调用:编译时一般会报警告,极少数情况下不会报警告。但是最好加上声明。
3、如果没有调用,只有定义和声明:编译时一般会报警告(有一个函数没有使用),有时不会报警告。这时候程序执行不会出错,只是你白白的写了几个函数,而没有使用浪费掉了而已。
实验:在一个项目的两个.c文件中,分别定义一个名字相同的函数,结果?
编译报错 multiple definition of `func_in_a'
结论:在一个程序中,不管是一个文件内,还是该程序的多个文件内,都不能出现函数名重复的情况,一旦重复,编译器就会报错。主要是因为编译器不知道你调用该函数时到底调用的是哪个函数,编译器在调用函数时是根据函数名来识别不同的函数的。
跨文件的变量引用
(1)通过实验验证得出结论:在a.c中定义的全局变量,在a.c中可以使用,在b.c中不可以直接使用,编译时报错 error: ‘g_a’ undeclared (first use in this function)
(2)想在b.c中使用a.c中定义的全局变量,有一个间接的使用方式。在a.c中写一个函数,然后函数中使用a.c中定义的该全局变量,然后在b.c中先声明函数,再使用函数。即可达到在b.c中间接引用a.c中变量的目的。
(3)想在b.c中直接引用a.c中定义的全局变量g_a,则必须在b.c中引用前先声明g_a,如何声明变量? extern int g_a;
extern关键字: extern int g_a; 这句话是一个全局变量g_a的声明,这句话告诉编译器,我在外部(程序中 不是本文件的另一个文件)某个地方定义了一个全局变量 int g_a,而且我现在要在这里引用它 告诉你编译器一声,不用报错了。
问题:
1、我只在b.c中声明变量,但是别的文件中根本就定义这个变量,会怎么样? 答案是编译报错(连接错误)undefined reference to `g_b'
2、我在a.c中定义了全局变量g_a,但是b.c中没有声明g_a,引用该变量会怎么样? 答案是直接抱错了,未定义
3、在a.c中定义,在b.c中声明,a.c和b.c中都没有引用该变量,会怎么样? 答案是不会出错。只是白白的定义了一个变量没用,浪费了
结论:不管是函数还是变量,都有定义、声明、引用三要素。其中,定义是创造这个变量或者函数,声明是向编译器交代它的原型,引用是使用这个变量或函数。所以如果没有定义只有声明和引用,编译时一定会报错。undefined reference to `xxx'
在一个程序里面,一个函数可以定义一次,引用可以有无数次,声明可以有无数次。因为函数定义或者变量的定义实际上是创造了这个函数/变量,所以只能有一次。(多次创造同名的变量会造成变量名重复,冲突;多次创造同名的函数也会造成函数名重名冲突)。声明是告诉编译器变量/函数的原型,在每个引用了这个全局变量/函数的文件之前都要声明该变量/函数
局部变量能不能跨文件使用? 不能。因为局部变量属于代码块作用域。他的作用域只有他定义的那个函数内部。
静态局部变量能不能跨文件使用? 不能。因为本质上还是个局部变量。
讨论跨文件使用问题,只用讨论全局变量和函数就可以了
c语言函数定义、函数声明、函数调用以及extern跨文件的变量引用的更多相关文章
- 小心C语言的定义与声明
小心C语言的定义与声明 转自360博客 注:为便于说明问题,文中提及的变量和函数都被简化. 一.起源 DBProxy在测试过程中,发现对其执行某步管理操作后,程序有时会崩溃,但不是每次都出现. 二.G ...
- C++: 模板函数定义与声明分离;
我们知道模板函数或模板类的定义一般都是和声明一起在头文件中,但是这样的话, 就暴露了内部实现,有什么办法能够将定义和声明进行分离呢? 答案是: 有的: 头文件: test.h; class test ...
- C 语言宏定义函数编写时 do-while 的妙用和一些注意事项
在 C 语言中,我们都知道可以用宏定义来编写函数,一般称为宏函数.如果一个宏函数比较复杂,那么在编写这样的宏函数是有一定技巧和注意事项的.文章给出一些我认为值得关注的地方,以及一些注意事项(个人建议) ...
- 410 for 循环 运算 改变循环的控制流 死循环 遍历数组 定义方法 有名函数匿名函数 定义函数的方法取值 date math 局部变量 函数 局部与全局变量 次幂/随机数/取绝对值/向上取整/平方根
for(1.表达式1;2.表达式2;3.表达式3){ 4.循环体语句; } 先执行1 ,在执行2, 表达式, 如果2结果为false,退出循环 如果2是true 执行4 在执行3 执行2 举例打印1- ...
- python函数基础:调用内置函数&定义函数
调用内置函数 有很多内置函数,在使用中需要积累.这里只举两个例子: 分别调用abs和数据类型转换,注意当入参类型错误时候会报错 ''' print('abs(-100)') abs(-100) pri ...
- Delphi中函数定义和声明的位置
当函数(或过程)A定义在函数(或过程)B之前,那么函数B就可以调用函数A,并且编译成功,例如下面的 procedure TForm1.btn1Click(Sender: TObject); 和 f ...
- C语言宏定义函数中的“_##”的意思
最近在看google vp9的代码的时候碰到: #define intra_pred_sized(type, size) \ void vp9_##type##_predictor_##size##x ...
- for循环的运算 改变循环的控制流 死循环 遍历数组 定义方法 有名函数匿名函数 定义函数的方法取值 与 自己创建函数取值 局部与全局变量 次幂/随机数/取绝对值/向上取整/平方根
今天学习的是for循环,对for循环的运算有了理解. document.write(" ")里的内容在网页上展示出来 有名函数非常重要!!!!!!!!!!!!!!!!!!!!!并且 ...
- 廖雪峰网站:学习python函数—定义函数(二)
def my_abs(x): if x >= 0: return x else: return -x print(my_abs(-99)) # 空函数 def nop(): pass # 参数检 ...
随机推荐
- JS(六)
没有视频看了,心里有点慌啊,像这种每天都会灌输很多知识的学习方式,我觉得提前预习真的是有奇效,不然不容易跟上老师的思维. 1.发送验证码:简单 <!DOCTYPE html> <ht ...
- 【初学者常见问题】一脚踏入protected埋下的陷阱
受保护的(protected)——声明该成员的类的子类可以访问这个类的成员(但有一定的限制),并且,声明该成员的包内部的任何类也可以访问这个成员 protected修饰符参考:http://www.3 ...
- Delphi TStringList的用法
Delphi TStringList的用法 TStrings是一个抽象类,在实际开发中,是除了基本类型外,应用得最多的. TStringList 常用方法与属性: var List: TStringL ...
- Javascript:sort()方法快速实现对数组排序
定义和用法: sort() 方法用于对数组的元素进行排序. 语法: arrayObject.sort(sortby) 注释:sortby,可选,规定排序顺序,必须是函数. 说明: 如果调用该方法时没有 ...
- 【剑指Offer学习】【面试题56:链表中环的入口结点】
题目:一个链表中包括环.怎样找出环的入口结点? 解题思路 能够用两个指针来解决问题.先定义两个指针P1和P2指向链表的头结点.假设链表中环有n个结点,指针P1在链表上向前移动n步,然后两个指针以同样的 ...
- Hadoop在Windows环境下的部署[转]
http://blog.csdn.net/ruby97/article/details/7423088 经过一整天的折腾,参考了网上很多资料,我机器上的Hadoop似乎是配置成功了.下面分享一下详细的 ...
- 服务 IntentService 前台服务 定时后台服务
Activity public class MainActivity extends ListActivity { private int intentNumber = 0; @Ove ...
- Senparc.Weixin.MP SDK 微信公众平台开发教程 索引
Senparc.Weixin.MP SDK从一开始就坚持开源的状态,这个过程中得到了许多朋友的认可和支持. 目前SDK已经达到比较稳定的版本,这个过程中我觉得有必要整理一些思路和经验,和大家一起分享. ...
- Cretiria查询应用(一)
1.查询所有 Criteria criteria=session.createCriteria(Dept.class); //调用list()方法 List<Dept> li ...
- Search 和 Select比较 - 浅谈
Search 语法: public IFeatureCursor Search ( IQueryFilter filter, bool Recycling); Select 语法: pub ...