一、预备知识

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. php压缩zip文件类

    使用文件压缩类, 注意传的路径是相对路径.如果传绝对路径就把addFile里面的第二个参数去掉/ $zip = new ZipFolder(); $zipFile = './autoloadClass ...

  2. CF1483F口胡

    <线 性 做 法> 首先我们对所有串建立 ACAM,不难发现对于一个 \(i\),可能的 \(j\) 一定是 \(i\) 所有后缀节点在 fail 树上第一个被打标记的祖先. 但是这些祖先 ...

  3. LGP4229题解

    某位寄吧的故事 下文的 \(m\) 即为题面中的 \(Q\). 离散化,把序列变成 \(O(2m)\) 个部分,然后对这 \(O(2m)\) 个部分把最大值求出来,每次把最大值相同的部分拉出来,再把限 ...

  4. Linux服务器上搭建Centos7.0+Apache+php+Mysql网站

    一.安装Linux系统 1.1虚拟机搭建Linux Centos7.0版本,搭建过程省略. 二. 安装apache.php.mysql.php-gd等组件. 2.1安装Apache服务程序(apach ...

  5. golang实现WebSocket的商业化使用的开发逻辑(1)

    WebSocket是什么 WebSocket 是一种在单个 TCP 连接上进行全双工通信的协议.其最大特点之一就是:服务器可以主动向客户端推送信息,客户端也可以主动向服务器发送信息,是真正的双向平等对 ...

  6. 华为云图引擎服务 GES 实战——创图

    本实验主要是熟悉 GES 的创图操作,GES 创图的大致流程如下所示. 环境准备 上传数据 导入元数据 创建图 环境准备 由于 GES 的原始数据是存在 OBS 上的,如果 OBS 上没有桶,需要按照 ...

  7. fiber核心(react 16)?

    旧: 浏览器渲染引擎单线程, 计算DOM树时锁住整个线程, 所有行为同步发生, 有效率问题, 期间react会一直占用浏览器主线程,如果组件层级比较深,相应的堆栈也会很深,长时间占用浏览器主线程, 任 ...

  8. 【Java面试宝典】什么情况下会发生栈内存溢出?

    如果线程请求的栈深度大于虚拟机所允许的深度,将抛出StackOverflowError异常. 如果虚拟机在动态扩展栈时无法申请到足够的内存空间,则抛出OutOfMemoryError异常.

  9. 数据库中的ACID

    参考链接:什么是ACID 数据库中的锁机制

  10. 解释 Spring 框架中 bean 的生命周期?

    Spring 容器 从 XML 文件中读取 bean 的定义,并实例化 bean. Spring 根据 bean 的定义填充所有的属性. 如果 bean 实现了 BeanNameAware 接口,Sp ...