一、预备知识

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. think php 图像加水印

    1.将下载好的字体引入至 thinkPHP 框架的public/static 下(这里我建了一个文件夹叫font) (1.) (2.)   2.将字体路径写入config.php中 'font'=&g ...

  2. egg微信小程序支付(服务商)插件封装

    下单 通过下单获取prepay_id,然后返回给小程序发起支付 若是服务商,mch_id:传入服务的商户号:sub_mch_id:传入子商户的商户号,算法签名的秘钥是服务商的秘钥. 'use stri ...

  3. 通过IMM With Remote Console为服务器安装操作系统

    现有IBM System x3750 M4(8722A1C)配置   产品类别 机架式 产品结构 2U CPU类型 Intel 至强E5-4600 CPU型号 Xeon E5-4640 CPU频率 2 ...

  4. 【ASP.NET Core】MVC 控制器的模型绑定(宏观篇)

    欢迎来到老周的水文演播中心. 咱们都知道,MVC的控制器也可以用来实现 Web API 的(它们原本就是一个玩意儿),区别嘛也就是一个有 View 而另一个没有 View.于是,在依赖注入的服务容器中 ...

  5. SpringBoot在线预览PDF文件(引用pdf.js工具)

    本项目Demo使用了PDF.js插件实现PDF在线阅读功能PDF.js插件下载地址 实测能用! 1.创建SpringBoot项目,目录结构如下: 2.进行项目配置: pom.xml: <proj ...

  6. 4月4日 python学习总结 os pickle logging

    1.序列化和反序列化 我们把对象(变量)从内存中变成可存储或传输的过程称之为序列化,在Python中叫pickling. 反过来,把变量内容从序列化的对象重新读到内存里称之为反序列化,即unpickl ...

  7. CF1487G String Counting (容斥计数)

    传送门 考虑$c[i]>n/3$这个关键条件!最多有2个字母数量超过$n/3$! 没有奇数回文?长度大于3的回文串中间一定是长度为3的回文串,所以合法串一定没有长度=3的回文,也就是$a[i]\ ...

  8. python实现AES加密、解密

    AES加密方式有五种:ECB, CBC, CTR, CFB, OFB 从安全性角度推荐CBC加密方法,本文介绍了CBC,ECB两种加密方法的python实现 python 在 Windows下使用AE ...

  9. 面试问题之C++语言:C++中指针和引用的区别

    转载于:https://blog.csdn.net/gcc2018/article/details/82285940 1.指针是一个变量,只不过这个变量存储的是一个地址,指向内存的一个存储单元:而引用 ...

  10. SpringDataRedis的Keyspaces设置

    前言 原文:https://docs.spring.io/spring-data/redis/docs/2.3.2.RELEASE/reference/html/#redis.repositories ...