C语言中extern,static, register,volatile 关键字的作用;保姆级教学!

目录

前言:

一.extern

 二.static

 三.register

四.volatile 

最后

冰冻三尺非一日之寒。既然选择远方,当不负青春,砥砺前行,每一个裂缝都是为透出光而努力,只有极致的拼搏,才能配得上极致的风景。诸君,山顶见!


前言:

在C语言中,这几个关键字,都有他们自己的个性。static和extern用的比较多,特别是static在学校的C语言考试经常考到。register和volatile这两个关键字是平时用的比较少,如果小伙伴对这两个关键字的作用已经有了认识,那小编就要给你树个大拇指了,小伙子了不起。小编自己也曾在考试中在static这个关键字上吃了憋,自以为C语言学的不错的情况下,见到register和volatile也是一脸懵,今天特意来聊一聊这几个关键字。

一.extern

extern声明外部符号,用来声明不在同一个源文件( .c文件)的变量,这里非常像引用头文件,但是引用头文件仅限于,变量在   .h 文件中,我们可以使用#include"xxx.h",但是如果是在 .c 文件中就不可以用头文件了。

看代码示例,这里是引用头文件的情况。

再来演示一下,外部变量在.c文件中;

 注意:这里的a通过extern去声明,这里外部文件的a,必须是全局变量,因为局部变量的作用域仅在自己所在的局部范围中,局部变量的生命周期也是进入作用范围开始和出作用范围结束,而全局变量的作用范围是整个工程,生命周期是整个程序的生命周期,如果a是局部变量,在外部声明了a,而a的生命周期已经结束了,编译器都不会编译通过。

extern对于函数也是一样的,用法和普通全局变量一样。

但是函数一般不加也可以,但是可能会报未声明的警告。

 二.static

1.static的作用是,被static修饰局部变量,会改变局部变量的储存类型,对于普通的局部变量是存储在栈区的,被static修饰的变量是存储在静态区的。存储在静态区的变量出了作用范围依然不会销毁,依然存在。所以静态变量的生命周期是整个程序的生命周期,只有程序结束的时候静态区的变量才会回收。这里的对静态区的变量描述是不是非常像全局变量,没错全局变量也是存储在静态区的。其实除了静态区和栈区,还有一个堆区。

 写一段代码来看看static是怎样延长变量的生命周期的:

#include<stdio.h>
void text()
{
	int a = 0;
	a++;
	printf("%d ", a);
}
int main()
{
	for (int i = 0; i < 5; i++)
	{
		text();
	}
	return 0;
}

 小伙伴们可以算一算这段代码的运行结果。

小伙伴们有没有算对呢,因为这里的a是个局部变量;所以每次进入函数text(),a变量都会重新创建,所以每次a变量的值都是a=0+1;出了函数 a变量就会销毁。

 下面再来看一看这个代码:

#include<stdio.h>
void text()
{
	static int a = 0;
	a++;
	printf("%d ", a);
}
int main()
{
	for (int i = 0; i < 5; i++)
	{
		text();
	}
	return 0;
}

小伙伴来算一算结果吧

 为什么会这样呢?

 由此可见,局部变量的生命周期延长了,但是作用域还是不变的。

2.如果static修饰全局变量,又会是怎么样的呢?一起来看一看吧。

首先全局变量具有外部链接属性,static修饰后,外部连接属性就变成了,内部连接属性。这个全局变量就只能在自己所在的.c文件看到,其他源文件就无法访问。

 修饰函数也会使得函数外部连接属性就变成内部连接属性。函数就只能在自己所在的.c文件看到,其他源文件就无法访问。

 三.register

register叫做寄存器,被其修饰的变量叫做,寄存器变量。什么是寄存器简单介绍一下,计算机的存储位置有,硬盘,内存,高速缓存,寄存器。

 当一个变量,后续需要大量使用的时候,每次CPU都要向寄存器,高速缓存,内存一级一级的去寻找,这样访问速度就会很慢,针对这样的情况,如果我们就将这样的变量存储到寄存器中,那么CPU每次都直接从寄存器中去获取,访问速度就会大大提高。所以register关键字由此出现,但是register修饰变量,只是建议将变量存储到寄存器中,会根据情况而定,不是被register修饰了就一定放到寄存器中,这点要特别注意。编译器会根据情况自己智能分析的将,需要的处理的变量放到寄存器中。还有就是被register修饰的变量是不能取地址的,是因为&只能取出内存中的地址,而无论被register修饰的变量,是否真正的存储到了寄存器中,都不能取地址。

四.volatile 

volaile 有不稳定的,容易变化的意思。当我们有一个变量需要大量的使用,这个变量就会,可能就会存储到寄存器中,在我们现在来看,看似没事,其实是有一定风险的,因为我们现在写的代码都是单线程的,如果代码不只有一个线程,而在另外的线程中会使得变量被修改,而CPU仍然从寄存器中去获取变量,获取的并不是修改后的变量,就会导致出现问题。而volatile就是使得被修饰的变量不去优化,一直放在内存中,提高对特殊地址位置的访问,使得后续的访问安全性更高。这里volatile和register有点对立,可以对比记忆。

值得注意的是,volatile修饰的变量也是提醒编译器,这个变量后续可能会发生变化,要注意保护。并不是被volatile修饰及一定发生变化。这点和register非常像。
 

最后

冰冻三尺非一日之寒。既然选择远方,当不负青春,砥砺前行,每一个裂缝都是为透出光而努力,只有极致的拼搏,才能配得上极致的风景。诸君,山顶见!

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

我的代码爱吃辣

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

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

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

打赏作者

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

抵扣说明:

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

余额充值