关键字static、extern、volatile、详解及举例
一、预备知识
1、 什么是局部变量?什么是全局变量?
所谓局部变量,就是指在函数内部定义的变量的,只在该函数范围内有效。
全局变量是指,在函数外部定义的变量为外部变量,即全局变量。它的有效范围是从定义变量的位置开始,到此源文件(如.c文件)结束的位置。这个变量在同一个工程中的其他源文件是没有起作用的。
2、变量的存储方式
从上面的分类中可以看出,从变量的作用域角度可以分为 局部变量和全局变量。其实,从变量的存在的时长来看,可以分为静态存储方式和动态存储方式。
那么,什么是静态存储方式?什么是动态存储方式呢?
静态存储方式就是在程序运行的时候,由系统分配的,固定的存储空间的方式。比如,有的变量在程序运行的整个过程都是一直存在的,就是静态存储方式。
动态存储方式就是在程序运行时候,根据需要进行,动态分配存储空间的方式。比如,调用某个函数的时候,函数内的变量先是临时分配存储空间,然后调用结束后,再释放掉该部分的空间。函数的形参,函数中定义的局部变量,都是动态存储方式
二、关键字的含义到底是啥意思?
1 、Static是什么意思?
我们说过,局部变量在使用完之后,它的存储空间会被释放掉。如果我们不想将这些变量释放,而继续保留它的值,应该怎么办呢?这就应该使用static关键字进行声明。把这个局部变量指定为 “静态局部变量”。那么,下一次再次调用含有该变量的函数的时候,上一次调用的结果就会保留。因为它的存储空间一直没有变动过。
举个栗子,
1 #include<stdio.h>
2 int main()
3 {
4 int add(int a);//声明一个加法函数
5 int a = 2, i;
6 for (i = 0; i < 3; i++)
7 {
8 printf("%d\n", add(a)); //输出add(a)的值
9 }
10 }
11
12 //add函数的定义
13 int add(int a)
14 {
15 int b = 0;
16 static c = 3;
17 b = b + 1;
c = c + 1;
18 return (a + b + c);
19 }
不急,不用慌,我们来简单分析这个程序。
首先,主函数第一次调用了add函数,进入子函数,子函数中返回一个a+b+c即 2+1+4=7; 所以输出结果为7;
然后第二次再次调用add函数,如果没有static 关键字声明变量c, 那么依然执行2+1+4=7;但是,加上static之后,c的值不是初始时候的3,而是上一次执行c=c+1,之后改变成了4。第二次调用时候,c的值一开始已经变成了4,执行c=c+1后,变为5! 这就是static的魅力!所以,第二次执行结果为2+1+5=8;
同理,第三次调用add函数时候,c的值一开始已经变成了5,执行c=c+1后,变为6,输出结果为9;
故运行的结果为:

注:虽然静态局部变量在函数调用结束后,依然存在,但是其他函数是不能引用它的。因为它是局部变量,只能被本身的函数使用。
上面讲述的局部变量增加Static 的情行,我也见过全局变量的前面也加上static的声明,这又是什么意思呢?
有时候,在程序设计中,希望外部变量只限制在本文件中,不想让其他文件引用。那么可以在外部变量的定义处增加一个static声明;
如
file1.c static int M; //在外部变量加上static 声明;
int main()
{
....... }
这种变量,叫做静态外部变量。
2、extern 是啥意思?
前文提到,全局变量的作用范围,是指,从定义该变量的位置到该源文件结束的地方。但是呢,有的时候,我们想要扩大全局变量的范围,就需要使用extern关键字了。
全局变量的作用范围已经这么光了,还需要扩大?有以下几种情况是需要扩大的。
(1)在定义处之前的地方,是不能使用该外部变量的。可以用extern 声明一下;
(2)将外部变量的作用范围拓展到其他文件;
一个C程序是由很多给c源文件组成的,如果别的源文件也想共用这个变量(跨文件使用),那么,也需要用extern 声明;
举个栗子
在file1 文件中 写入下面内容:
#include<stdio.h>
int A; //定义一个全局变量
int main()
{
int add(int); //函数声明;
int b = 3, c=4, d,n ;
printf("enter the number A :\n");
scanf("%d,", &A); //输入A的值
d = A * b;
printf("%d *%d=%d\n", A, b, d); //输出 A*b n = add(c); printf("%d +%d=%d\n", A, c, n); }
在file2 文件中写入下面代码:
1 extern A;
2 int add(int n) //定义add函数;
3 {
4 return (A + n);
5 }
我们再来分析一下,首先main 函数中,计算了A*b的值,即A*3 ;假设A 输入5,那么第一个结果为 15;
后来执行了add 函数,计算了A+c的值,即 A+4 ;假设A 输入5,那么第二个结果为 9;
我们来看看是不是

注意:假设某个程序包括了5个源文件,在一个文件中定义了全局变量A,其他4个文件要想引用A,必须在每一个文件中都加上“extern A;”声明;
3、volatile 是啥意思?
先介绍一下cpu处理数据的过程,cpu从内存中读取到数据,然后放到cpu本身的寄存器中,然后经过计算使用,得到最终的结果值,再把结果写入的内存中。
volatile提醒编译器它后面所定义的变量随时都有可能改变,是不稳定的,易变化的。如果没有volatile关键字,则编译器可能优化读取和存储,可能暂时使用寄存器中的值,如果这个变量由别的程序更新了的话,将出现不一致的现象。
因此编译后的程序每次需要存储或读取这个变量的时候,都会直接从内存中读取数据。
举个栗子,
static int flag; void add(void)
{
flag = 0; while (flag != 5); }
上面这段代码,我们定义了flag 这个变量,设置它的值为0,然后while()进行无限循环,我们可以看到,如果只有这个程序,flag 的值不会变成5,永远都是0,那么编译器就会“擅作主张”地把它优化为如下:
void add_optimized(void) {
flag = 0;
while (true);
}
但是,flag 可能指向一个随时能被计算机其他部分修改的地址,比如硬件的寄存器。那么,被优化的代码就永远检测不到这样的修改变化,为了阻止编译器像上面那样优化代码,需要使用volatile关键字:
static volatile int flag;
这样修改以后,循环条件就不会被编译器优化掉,当值改变的时候系统将会检测到。
关键字static、extern、volatile、详解及举例的更多相关文章
- 【粉丝问答10】C语言关键字static的使用详解
视频地址:https://www.ixigua.com/6935761378816819748 粉丝提问 粉丝问题,总结一下: 关键字static的使用方法. 要想搞清楚关键字static的使用方法, ...
- const define static extern 关键词详解
const const关键词并不能把一个变量变成一个常量, 在符号前加上const表示这个符号不能被赋值, 即他的值对这个符号来说是只读的, 但并不代表这个值不能用其他方法去改变. 通过下面的例子就能 ...
- Java并发关键字Volatile 详解
Java并发关键字Volatile 详解 问题引出: 1.Volatile是什么? 2.Volatile有哪些特性? 3.Volatile每个特性的底层实现原理是什么? 相关内容补充: 缓存一致性协议 ...
- 黑马-----内存模型和volatile详解
黑马程序员:Java培训.Android培训.iOS培训..Net培训 JAVA线程-内存模型和volatile详解 一.单核内存模型 1.程序运行时,将临时数据存放到Cache中 2.将CPU计算所 ...
- extern用法详解
1 基本解释 extern可以置于变量或者函数前,以标示变量或者函数的定义在别的文件中,提示编译器遇到此变量和函数时在其他模块中寻找其定义. 另外,extern也可用来进行链接指定. 2 问题:ext ...
- c++ --> extern "C" {}详解
extern "C" {}详解 extern "C"的真实目的是实现类C和C++的混合编程.在C++源文件中的语句前面加上extern "C" ...
- C# static的用法详解
C# static的用法详解 有的东西你天天在用,但未必就代表你真正了解它,正如我之前所了解的 static . 一.静态类 静态类与非静态类的重要区别在于静态类不能实例化,也就是说,不能使用 n ...
- Linux防火墙iptables学习笔记(三)iptables命令详解和举例[转载]
Linux防火墙iptables学习笔记(三)iptables命令详解和举例 2008-10-16 23:45:46 转载 网上看到这个配置讲解得还比较易懂,就转过来了,大家一起看下,希望对您工作能 ...
- 编程中,static的用法详解
C++的static有两种用法:面向过程程序设计中的static和面向对象程序设计中的static.前者应用于普通变量和函数,不涉及类:后者主要说明static在类中的作用.一.面向过程设计中的sta ...
- c中常用的关键字static const volatile
在C语言中,关键字static有三个明显的作用:1). 在函数体,一个被声明为静态的变量在这一函数被调用过程中维持其值不变.2). 在模块内(但在函数体外),一个被声明为静态的变量可以被模块内所用函数 ...
随机推荐
- php7废弃mcrypt加密,使用openssl替换
概要: php从7.0升级到7.1废弃了一个扩展,即mcrypt扩展,虽然安装上扩展也能正常使用,但是会发出警告,告诉我们mcrypt相关方法已经被废弃,到了7.2,已经被移除,因此不建议继续使用. ...
- 微信小程序码生成及canvas绘制
吐槽:某厂的开发文档写的跟屎一样 1.后台返回accessToken,小程序请求获取小程序码 uni.request({ url: 'https://api.weixin.qq.com/wxa/get ...
- 06 for循环 增强for循环 练习
for循环 //九九乘法表 //1.打印第一列 //2.我们固定的1再用一个循环包起来 //3.去掉重复项,i <= j //4.调整样式 for(int j=1;j <=9;j++){ ...
- Python列表生成
# For More :http://www.codebelief.com/article/2017/02/python-advanced-programming-list-comprehension ...
- MySQL between and 边界测试
看到有一些博客说 between and 有不含边界的情况,于是测试了一把,记录如下.先说结论:between and 不存在不含边界的情况 1. between and 是包含边界的 id betw ...
- rsync同步文件到远程机器,卡住10多秒--问题解决过程
背景 以前大体介绍过,我们这边是做运维平台的.如果要形象化理解,那么,比如jenkins这种喜闻乐见的软件大致了解吧,jenkins就经常需要同步文件/版本包到远程机器上,jenkins怎么实现的,没 ...
- Blazor 001 : 一个激进的Web开发框架
本文从比较高的位置俯瞰一下 .NET Blazor 技术方向,主要是给大家介绍一下"什么是 Blazor" 文章后半部分会给出一个 Blazor 中的 Hello World 示例 ...
- [转载]我的WafBypass之道(upload篇)
现在位置: 首页 > 文章 > Web安全 > 正文 我的WafBypass之道(upload篇) 2016 /11/30 15:20 4,901 沙发 0x00 前言 玩waf当然 ...
- 【编程教室】Python绘制冬奥吉祥物“冰墩墩”
大家好,欢迎来到 Crossin的编程教室 ! 这两天,随着北京冬奥会的开幕,吉祥物"冰墩墩"可是火出了圈,多少人排长队都买不到.据说甚至有人把价格炒到了几千元. 就连昨天的&qu ...
- 为什么要用 Spring Boot?
Spring Boot 优点非常多,如:独立运行简化配置自动配置无代码生成和XML配置应用监控上手容易Spring Boot 集这么多优点于一身,还有理由不使用它呢?