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

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

前言:

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


一.extern

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


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


412440bbb3b740b7b698f5bdc2b58d5a.png


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


db0886e2e04440dd9ddaf84b77a20cc4.png


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


f24c17c6be6646108a24e7d17fd86ea5.png


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


678ff1db62864dceb8bbe7434a9a87b7.png


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


二.static

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


7666af74662045bc8615d76d9c32ae43.png


写一段代码来看看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叫做寄存器,被其修饰的变量叫做,寄存器变量。什么是寄存器简单介绍一下,计算机的存储位置有,硬盘,内存,高速缓存,寄存器。


38e5c68763374524b4344a20d8fe774c.png


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


四.volatile

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


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


最后

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


相关文章
|
1月前
|
存储 C语言
【C语言函数】static和extern关键字修饰
【C语言函数】static和extern关键字修饰
|
2月前
|
C语言
|
2月前
|
存储 C语言
C语言中static关键字的作用与用法解析
C语言中static关键字的作用与用法解析
|
3月前
|
存储 C语言
C语言中的typedef关键字:为类型定义新名称
C语言中的typedef关键字:为类型定义新名称
|
3月前
|
C语言
深入探索C语言中的sizeof关键字
深入探索C语言中的sizeof关键字
|
4月前
|
C语言
C语言中关键字static的三种用法
C语言中关键字static的三种用法
|
存储 编译器 C语言
【C语言】关键字static——static修饰局部变量、全局变量和函数详解!
【C语言】关键字static——static修饰局部变量、全局变量和函数详解!
305 0
|
存储 Java 编译器
【C语言】静态关键字static的用法(详解)
不同于其他关键字,他们都有多种用法,而且在一定环境下使用,可以提高程序的运行性能,优化程序的结构。这篇文章主要介绍了C语言中静态关键字static的作用,对大家学习C语言非常有帮助。
146 0
C语言关键字static的三种用法
作用域和生命周期的介绍 static修饰局部变量 static修饰全部变量 static修饰函数 作用域和生命周期的介绍 什么样的变量称为局部变量呢?
|
存储 编译器 C语言
C语言关键字之extern和static
C语言关键字之extern和static