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语言程序设计——函数】亲密数判定(头歌实践教学平台习题)【合集】
本文介绍了通过编程实现打印3000以内的全部亲密数的任务。主要内容包括: 1. **任务描述**:实现函数打印3000以内的全部亲密数。 2. **相关知识**: - 循环控制和跳转语句(for、while循环,break、continue语句)的使用。 - 亲密数的概念及历史背景。 - 判断亲密数的方法:计算数A的因子和存于B,再计算B的因子和存于sum,最后比较sum与A是否相等。 3. **编程要求**:根据提示在指定区域内补充代码。 4. **测试说明**:平台对代码进行测试,预期输出如220和284是一组亲密数。 5. **通关代码**:提供了完整的C语言代码实现
58 24
|
28天前
|
存储 C语言
【C语言程序设计——函数】递归求斐波那契数列的前n项(头歌实践教学平台习题)【合集】
本关任务是编写递归函数求斐波那契数列的前n项。主要内容包括: 1. **递归的概念**:递归是一种函数直接或间接调用自身的编程技巧,通过“俄罗斯套娃”的方式解决问题。 2. **边界条件的确定**:边界条件是递归停止的条件,确保递归不会无限进行。例如,计算阶乘时,当n为0或1时返回1。 3. **循环控制与跳转语句**:介绍`for`、`while`循环及`break`、`continue`语句的使用方法。 编程要求是在右侧编辑器Begin--End之间补充代码,测试输入分别为3和5,预期输出为斐波那契数列的前几项。通关代码已给出,需确保正确实现递归逻辑并处理好边界条件,以避免栈溢出或结果
61 16
|
1月前
|
C语言
【C语言程序设计——循环程序设计】枚举法换硬币(头歌实践教学平台习题)【合集】
本文档介绍了编程任务的详细内容,旨在运用枚举法求解硬币等额 - 循环控制语句(`for`、`while`)及跳转语句(`break`、`continue`)的使用。 - 循环嵌套语句的基本概念和应用,如双重`for`循环、`while`嵌套等。 3. **编程要求**:根据提示在指定区域内补充代码。 4. **测试说明**:平台将对编写的代码进行测试,并给出预期输出结果。 5. **通关代码**:提供完整的代码示例,帮助理解并完成任务。 6. **测试结果**:展示代码运行后的实际输出,验证正确性。 文档结构清晰,逐步引导读者掌握循环结构与嵌套的应用,最终实现硬币兑换的程序设计。
51 19
|
1月前
|
算法 C语言
【C语言程序设计——循环程序设计】求解最大公约数(头歌实践教学平台习题)【合集】
采用欧几里得算法(EuclideanAlgorithm)求解两个正整数的最大公约数。的最大公约数,然后检查最大公约数是否大于1。如果是,就返回1,表示。根据提示,在右侧编辑器Begin--End之间的区域内补充必要的代码。作为新的参数传递进去。这个递归过程会不断进行,直到。有除1以外的公约数;变为0,此时就找到了最大公约数。开始你的任务吧,祝你成功!是否为0,如果是,那么。就是最大公约数,直接返回。
73 18
|
1月前
|
Serverless C语言
【C语言程序设计——循环程序设计】利用循环求数值 x 的平方根(头歌实践教学平台习题)【合集】
根据提示在右侧编辑器Begin--End之间的区域内补充必要的代码,求解出数值x的平方根;运用迭代公式,编写一个循环程序,求解出数值x的平方根。注意:不能直接用平方根公式/函数求解本题!开始你的任务吧,祝你成功!​ 相关知识 求平方根的迭代公式 绝对值函数fabs() 循环语句 一、求平方根的迭代公式 1.原理 在C语言中,求一个数的平方根可以使用牛顿迭代法。对于方程(为要求平方根的数),设是的第n次近似值,牛顿迭代公式为。 其基本思想是从一个初始近似值开始,通过不断迭代这个公式,使得越来越接近。
52 18
|
1月前
|
C语言
【C语言程序设计——循环程序设计】统计海军鸣放礼炮声数量(头歌实践教学平台习题)【合集】
有A、B、C三艘军舰同时开始鸣放礼炮各21响。已知A舰每隔5秒1次,B舰每隔6秒放1次,C舰每隔7秒放1次。编程计算观众总共听到几次礼炮声。根据提示,在右侧编辑器Begin--End之间的区域内补充必要的代码。开始你的任务吧,祝你成功!
49 13
|
1月前
|
存储 安全 C语言
【C语言程序设计——选择结构程序设计】预测你的身高(头歌实践教学平台习题)【合集】
分支的语句,这可能不是预期的行为,这种现象被称为“case穿透”,在某些特定情况下可以利用这一特性来简化代码,但在大多数情况下,需要谨慎使用。编写一个程序,该程序需输入个人数据,进而预测其成年后的身高。根据提示,在右侧编辑器补充代码,计算并输出最终预测的身高。分支下的语句,提示用户输入无效。常量的值必须是唯一的,且在同一个。语句的作用至关重要,如果遗漏。开始你的任务吧,祝你成功!,程序将会继续执行下一个。常量都不匹配,就会执行。来确保程序的正确性。
48 10
|
1月前
|
小程序 C语言
【C语言程序设计——基础】顺序结构程序设计(头歌实践教学平台习题)【合集】
目录 任务描述 相关知识 编程要求 测试说明 我的通关代码: 测试结果: 任务描述 相关知识 编程编写一个程序,从键盘输入3个变量的值,例如a=5,b=6,c=7,然后将3个变量的值进行交换,使得a=6,b=7,c=5。面积=sqrt(s(s−a)(s−b)(s−c)),s=(a+b+c)/2。使用输入函数获取半径,格式指示符与数据类型一致,实验一下,不一致会如何。根据提示,在右侧编辑器补充代码,计算并输出圆的周长和面积。
39 10
|
27天前
|
存储 编译器 C语言
【C语言程序设计——函数】分数数列求和2(头歌实践教学平台习题)【合集】
函数首部:按照 C 语言语法,函数的定义首部表明这是一个自定义函数,函数名为fun,它接收一个整型参数n,用于指定要求阶乘的那个数,并且函数的返回值类型为float(在实际中如果阶乘结果数值较大,用float可能会有精度损失,也可以考虑使用double等更合适的数据类型,这里以float为例)。例如:// 函数体代码将放在这里函数体内部变量定义:在函数体中,首先需要定义一些变量来辅助完成阶乘的计算。比如需要定义一个变量(通常为float或double类型,这里假设用float。
34 3
|
27天前
|
存储 算法 安全
【C语言程序设计——函数】分数数列求和1(头歌实践教学平台习题)【合集】
if 语句是最基础的形式,当条件为真时执行其内部的语句块;switch 语句则适用于针对一个表达式的多个固定值进行判断,根据表达式的值与各个 case 后的常量值匹配情况,执行相应 case 分支下的语句,直到遇到 break 语句跳出 switch 结构,若没有匹配值则执行 default 分支(可选)。例如,在判断一个数是否大于 10 的场景中,条件表达式为 “num> 10”,这里的 “num” 是程序中的变量,通过比较其值与 10 的大小关系来确定条件的真假。常量的值必须是唯一的,且在同一个。
16 2

热门文章

最新文章