C语言深度剖析(二) --关键字(2)

0. 前言

首先来看一个问题
如果我有两个.c文件,main.ctest.c
在这里插入图片描述

相信第一反应是:不可以,需要先extern声明一下
我们来看一下结果
在这里插入图片描述
虽然会有一些警告,显然是可以的,那么是为什么呢?

为什么不同的.c文件中的函数可以直接调用呢?
这是因为

程序去找show函数的定义是什么时候呢?
是在程序最后一步链接生成可执行文件(.obj)的时候
也就是说
在编译的时候,编译器在本源文件中可能没有找到show函数(这时候,不同源文件中的内容是不互通的)
这时候就生成了警告,但是在最后一步链接的时候,编译器会到其他.c文件中寻找show函数,如果找到了,就可以正常运行,如果连接的时候还找不到,就会报错了!

在这里插入图片描述

在这里插入图片描述
解决方法:
利用extern声明全局变量
在这里插入图片描述
而如果extern的时候进行赋值可以吗?
!不可以
在这里插入图片描述
因为声明并不会开辟空间,=100叫做赋值或者初始化
而赋值或者初始化的前提就是需要有空间
而这里没有开辟空间,自然就会报错!
所有的变量声明的时候,不能设置初始值!

1. 为什么要用.h文件

在这里插入图片描述

2. .h文件中的声明

写在.h文件中的内容主要有

  1. C头文件
  2. 所有的变量的声明
  3. 所有的函数的声明
  4. #define,类型typedef ,struct

变量的声明

extern g_val;

函数的声明

不需要带函数体 {} 因为函数体的作用是开辟空间,声明不需要开辟空间

extern void show();

注意:
函数声明可以不带extern
但是全局变量必须要带extern
原因

  1. 全局变量需要带extern: int g_val 容易被编译器误认为是没初始化的定义
  2. 函数可以不带:函数声明后面的分号;就可以告诉编译器后面没有函数体,只是声明

3. static关键字

两个问题:

  1. 全局变量可以跨文件访问吗
  2. 函数可以跨文件访问吗

答案都是可以!
那么有没有具体的应用场景,我们不想让全局变量或者函数跨文件访问,只在本文件内部被访问?
这时候就用到static关键字了

static修饰全局变量

static修饰局部变量,则该变量只在本文件内被访问,不能被其他文件直接访问,但可以间接访问,修改的是全局变量的作用域
在这里插入图片描述
虽然不能直接访问,但是可以借助函数来间接访问
如图:
在这里插入图片描述
这样就可以利用调用show函数来实现访问static修饰的g_val变量了!

static修饰函数

static修饰某一个函数,该函数只能在本文件内被访问,不能在外部其他文件直接访问,只能间接访问
也可以理解成缩小了函数的作用域
在这里插入图片描述
如图 如果把show函数用static修饰起来,那么就会出现以下错误
在这里插入图片描述
也就是不可以直接访问show函数了
但是可以利用一个其他函数来间接访问show函数
在这里插入图片描述

static修饰局部变量

static修饰局部变量,更改该局部变量的生命周期,该局部变量的空间不会被释放!直到工程结束才会释放

一旦一个局部变量被static修饰,初始化动作只有一次(第一次),因为定义只有一次!

但并不是局部变量就变成了全局变量
作用域还是本代码块
只是它的生命周期变成了全局!

例子:

我们知道,局部变量具有临时性,函数调用开辟空间并初始化,
当函数结束的时候,释放空间还给操作系统,这时候变量就销毁了
看一个例子
在这里插入图片描述
运行结果:
在这里插入图片描述
每一次调用fun函数都会新创建一个i,结束函数的时候销毁,所以每一次的i是相同的

如果用static修饰局部变量 i
结果是:
在这里插入图片描述
我们打印地址来看一下
在这里插入图片描述

在这里插入图片描述
可以看到,每一次的地址都是相同的,也就是说明该局部变量没有被释放!

实际上static是C语言中一种安全机制
进行项目维护,提供安全保证
你不想让别人用的函数或者全局变量就可以用static修饰,这样别人就没法直接使用这些内容了

4. 为什么默认允许函数和全局变量跨文件访问

因为有一定规模的项目,一定是多文件的,多个文件之间,后序需要进行数据"交互"
可以通过包含头文件#include"test.h" 来使得main.c里面可以使用test.c中的函数或者变量
而如果不能进行跨文件,那么”交互成本" 就比较高,即使利用头文件也不能跨文件使用,借助别的东西间接访问,成本太高了

但是总有一些需要隐藏的内容
这时候就体现出static的作用了

5. 两个拓展问题

  • 为什么临时变量具有临时性
  • 为什么全局变量的生命周期是全局的

如图是一个 进程地址空间
在这里插入图片描述

  1. 局部变量都是放在栈区的,栈区会有出栈和压栈的过程,定义一个变量就会压栈,销毁一个变量就会出栈,这个过程是动态的,栈区的变量具有临时性,所以局部变量(临时变量)具有临时性
  2. 全局变量或者用static修饰的变量并不存放在栈区,他们放在全局数据区,全局数据区的数据在整个“进程”运行的生命周期内都是有效的,“进程”就是运行中的程序
  • 4
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

2021狮子歌歌

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值