一、预备知识

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、详解及举例的更多相关文章

  1. 【粉丝问答10】C语言关键字static的使用详解

    视频地址:https://www.ixigua.com/6935761378816819748 粉丝提问 粉丝问题,总结一下: 关键字static的使用方法. 要想搞清楚关键字static的使用方法, ...

  2. const define static extern 关键词详解

    const const关键词并不能把一个变量变成一个常量, 在符号前加上const表示这个符号不能被赋值, 即他的值对这个符号来说是只读的, 但并不代表这个值不能用其他方法去改变. 通过下面的例子就能 ...

  3. Java并发关键字Volatile 详解

    Java并发关键字Volatile 详解 问题引出: 1.Volatile是什么? 2.Volatile有哪些特性? 3.Volatile每个特性的底层实现原理是什么? 相关内容补充: 缓存一致性协议 ...

  4. 黑马-----内存模型和volatile详解

    黑马程序员:Java培训.Android培训.iOS培训..Net培训 JAVA线程-内存模型和volatile详解 一.单核内存模型 1.程序运行时,将临时数据存放到Cache中 2.将CPU计算所 ...

  5. extern用法详解

    1 基本解释 extern可以置于变量或者函数前,以标示变量或者函数的定义在别的文件中,提示编译器遇到此变量和函数时在其他模块中寻找其定义. 另外,extern也可用来进行链接指定. 2 问题:ext ...

  6. c++ --> extern "C" {}详解

    extern "C" {}详解 extern "C"的真实目的是实现类C和C++的混合编程.在C++源文件中的语句前面加上extern "C" ...

  7. C# static的用法详解

    C#   static的用法详解 有的东西你天天在用,但未必就代表你真正了解它,正如我之前所了解的 static . 一.静态类 静态类与非静态类的重要区别在于静态类不能实例化,也就是说,不能使用 n ...

  8. Linux防火墙iptables学习笔记(三)iptables命令详解和举例[转载]

     Linux防火墙iptables学习笔记(三)iptables命令详解和举例 2008-10-16 23:45:46 转载 网上看到这个配置讲解得还比较易懂,就转过来了,大家一起看下,希望对您工作能 ...

  9. 编程中,static的用法详解

    C++的static有两种用法:面向过程程序设计中的static和面向对象程序设计中的static.前者应用于普通变量和函数,不涉及类:后者主要说明static在类中的作用.一.面向过程设计中的sta ...

  10. c中常用的关键字static const volatile

    在C语言中,关键字static有三个明显的作用:1). 在函数体,一个被声明为静态的变量在这一函数被调用过程中维持其值不变.2). 在模块内(但在函数体外),一个被声明为静态的变量可以被模块内所用函数 ...

随机推荐

  1. NETPLIER : 一款基于概率的网络协议逆向工具(一)理论

    本文系原创,转载请说明出处:信安科研人 关注微信公众号 信安科研人 获取更多网络安全学术技术资讯 今日介绍一篇发表在2021 NDSS会议上的一项有关协议逆向的工作: @ 目录 1 网络协议逆向工程简 ...

  2. 《前端运维》一、Linux基础--05Shell运算符

    今天我们来学习下Shell运算符,Shell跟其他的编程语言一样,也支持多种运算符,包括: 算数运算符 关系运算符 布尔运算符 字符串运算符 文件测试运算符 那下面,我们就一一来学习一下这些运算符. ...

  3. Spring系列26:Spring AOP 通知与顺序详解

    本文内容 如何声明通知 如何传递参数到通知方法中 多种通知多个切面的通知顺序 多个切面通知的顺序源码分析与图解 声明通知 Spring中有5种通知,通过对应的注解来声明: @BeforeBefore ...

  4. Floyd算法 解决多元汇最短路问题

    接下来是图论问题求解最短路问题的最后一个,求解多元汇最短路问题 我们之前一般都是问1-n的最短路径,这里我们要能随便去问i到j的最短路径: 这里介绍一下Floyd算法:我们只有一个d[maxn][ma ...

  5. 6月11日 python学习总结 框架理论

    Web框架本质及第一个Django实例   Web框架本质 我们可以这样理解:所有的Web应用本质上就是一个socket服务端,而用户的浏览器就是一个socket客户端. 这样我们就可以自己实现Web ...

  6. 查找goog13的ip

    C:\Users\Deen>ping 172.217.24.14 Pinging 172.217.24.14 with 32 bytes of data: Reply from 172.217. ...

  7. 如何运行MATLAB和C++混合编程

    在GitHub下载了一个大佬的滤波器程序,包含MATLAB和C++,刚开始直接运行,发现提示如下: 然后,第一步:点击截图访问后面的链接,跳转到如下截图: 第二步:点击上面截图的左下角,R2015b版 ...

  8. python3 爬虫2--发送请求1

    1urlopen 属于url.request类 我们用urlopen("网址")来发送请求 最基础的发送请求如下 from urllib.request import urlope ...

  9. Mac安装和配置Maven 及其第二次启动报错问题解决

      1.下载安装 下载地址: https://maven.apache.org/download.cgi 下载后解压下来重名名为ApacheMaven,并放入到/usr/local/下 2.配置环境变 ...

  10. 一个".java"源文件中是否可以包括多个类(不是内部类)?有什么限制?

    可以有多个类,但只能有一个public的类,并且public的类名必须与文件的主文件名相同. 包含多个类的Java源文件编译之后会生成多个.class文件.