c 多文件全局变量_c的坑 -- static 和 extern

e06e96635b547ac2f660385d22fcea19.png

最近尝试回去使用c语言练练手感,但在做项目的时候就发现,我所理解的c语言跟真实的c语言差了十万八千里。不得不说,c++使用习惯了,就混淆了其和c语言的static关键字。在加上在c++中从来没有使用过extern所以也更加不会去正确使用。问题就出在这里,c语言的项目,大部分全局变量都由他们构成,所以你不能搞懂它俩,也就意味着你肯定不能够用c构建大项目的。

在知道这两关键字的根本的使用方式前,我们先来搞清楚下面几项,你选择什么会放在头文件(.h)中?

  1. #define 宏定义
  2. 全局变量
  3. 函数声明
  4. 函数定义

如果是几天前的我,除了4全部都放在头文件(.h)中。但是如果你是这样子做的话,那么你肯定会遇到一个坑,那就是2全局变量,你可以会遇到各种各样的错误。先看情况1,编译报错。

/* val.h */

这明摆着就是 a 被重定义了,那static的第一个作用就开始展示出来了,如果我们在上面 val.h 的 a 定义前加入 static 变量,他就能编译通过了。

/* val.h */

如果你学过c++那你一定和当时我想的一样,static关键字可以让a重定义覆盖旧的a。其实这样子说并不严谨,应该说static他可以做到限制变量,让他只能在当前文件可以读到。比如我们运行编译后的结果,你就能明白了。

func1

你可能马上恍然大悟,其实a他加上static变量之后,他不仅只有一个了,他分裂成三个了,每一个源文件(.c)都有一个自己的a变量,他看似是全局变量,却又不是全局变量,这就是static关键字的神奇之处。所以准确来说static变量如果你要放在头文件中,你就要做好出现每include一次,就多一个变量的情况。那如果static函数呢?效果跟变量一样。

/* val.h */

如果看到这你肯定很兴奋,那如果是 static 关键字定义的呢?然后再其他源文件中实现呢?那恭喜你,你获得进阶了。这种时候,没有定义实现的源代码文件(.c)是不可能使用的。

/* val.h */

因为我们在 func1.c 中定义了 func3 所以调用的时候没有任何毛病,但是如果你想在 main.c 中调用的话,他也只能去找自己的 func3 却不会去寻找 func1.c 的func3,因为 static 关键字限定了其查找的范围只能在自己的源文件中,定义了就有,没有定义就没有。

所以如果你想要使用全局变量的话,我个人建议是在源文件(.c)中定义,这样子能够保证其在整个项目中只存在一个。所以这就引出另外一个问题,你说函数它能够声明,变量他又声明不了,其他源代码又怎么读取其他源代码的全局变量,所以这就是 extern 关键字要做的,我觉得他真的有点像让变量声明的意味在里面。我们可以回到第一个例子中,在a声明前加入extern关键字。

/* val.h */

其实明摆着,他跟static不同,他是不会定义变量的,他也只是声明某处有一个a,如果你没有在某一个源文件(.c)中定义的话,就会出现链接错误。所以你要做的很简单,在某个源文件中定义 a 就行了。

/* main.c */

看到这里,其实你也明白了c语言其实他并不是以整体编译作为目标的,而是以源文件(.c)作为单位,然后后面将所获得的信息进行统一整合。一旦他在某处寻找到了结果,他就不会去其他地方寻找,包括后续include却找不到头文件也是一个道理,他都是以当前源文件所在位置进行判断和查找的,所以你这样子思考 static 和 extern 关键字的作用也是很简单明了的。

回到一开始的选择题中,你会选择什么放在头文件(.h)中?

End...

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值