linux中使用volatile(附加变量类型)

1  变量类型

1.1 自动变量特点

    (1)自动变量就是在函数内部定义的变量,只在内部有效

    (2)所以允许其他函数定义相同的变量

    (3)他们都有自己的区域性,没有连接性

    (4)自动变量分配内存就压栈,函数返回时退栈

    (5)一般不作专门说明的局部变量,均是自动变量,比如static说明

    (6)自动变量使用栈机制使用内存


1.2 静态变量static

1.2.1 局部静态变量

    (1)内存中的位置:静态存储区

    (2)未经初始化的全局静态变量会被程序自动初始化为0(自动对象的值是任意的,除非他被显示初始化)

    (3)当static用来修饰局部变量的时候,它就改变了局部变量的存储位置,从原来的栈中存放改为静态存储区,但是局部静态变量在离开作用域之后,并没有被销毁,而是仍然驻留在内存当中,值也保留,等程序下次再去执行这个函数,去使用它

    (4)当static用来修饰全局变量的时候,它就改变了全局变量的作用域(在声明他的文件之外是不可见的),但是没有改变它的存放位置,还是在静态存储区中。

1.2.2 全局静态变量

   (1)不会被其他文件所访问,修改

   (2)其他文件中可以使用相同名字的变量,不会发生冲突

    (3)内存中的位置:静态存储区(静态存储区在整个程序运行期间都存在)

    (4)未经初始化的全局静态变量会被程序自动初始化为0(自动对象的值是任意的,除非他被显示初始化)

1.2.3 静态函数

(1)其他文件中可以定义相同名字的函数,不会发生冲突

(2)静态函数不能被其他文件所用。


1.3  寄存器变量

(1)C语言中可以使用寄存器来优化程序性能,将一个常用变量声明成寄存器变量:resgister int i;如果可能的话,编译器会为他分配一个单独额寄存器,那函数执行期间对这个变量的操作全是对寄存器操作,就不用频繁去访问内存,读来读去,自然提高了程序的性能


1.4 易失变量:volatile

(1)表示变量是易失的,易变的

(2)强制访问内存操作,防止编译器去优化,告诉编译器每次必须去内存中取值,而不是寄存器或缓存中


1.5 非自动变量有两种 一种是全局变量,一种是静态变量

2 细说volatile

前言:一个定义为volatile的变量是说这变量可能会被意想不到地改变,这样,编译器就不会去假设这个变量的值了。精确地说就是,优化器在用到这个变量时必须每次都小心地重新读取这个变量的值,而不是使用保存在寄存器里的备份

2.1 volatile的定义与解释(对理解它很重要)cache的作用

(1)volatile关键字是一种类型修饰符,用它声明的类型变量表示可以被某些编译器未知的因素更改,比如:操作系统、硬件或者其它线程等。遇到这个关键字声明的变量,编译器对访问该变量的代码就不再进行优化,从而可以提供对特殊地址的稳定访问。 

(2)volatile 指出 i是随时可能发生变化的,每次使用它的时候必须从i的地址中读取,因而编译器生成的汇编代码会重新从i的地址读取数据放在b中。而优化做法是,由于编译器发现两次从i读数据的代码之间的代码没有对i进行过操作,它会自动把上次读的数据放在b中。而不是重新从i里面读。这样以来,如果i是一个寄存器变量或者表示一个端口数据就容易出错,所以说volatile可以保证对特殊地址的稳定访问。

            (3)volatile对应的变量可能在你的程序本身不知道的情况下发生改变   对于volatile类型的变量,系统每次用到他的时候都是直接从对应的内存当中提取,而不会利用cache当中的原有数值,以适应它的未知何时会发生的变化,系统对这种变量的处理不会做优化——显然也是因为它的数值随时都可能变化的情况。 

2.2 常使用到volatile的变量

(1)并行设备的硬件寄存器(如:状态寄存器) 
(2)一个中断服务子程序中会访问到的非自动变量(Non-automatic variables) 
(3)多线程应用中被几个任务共享的变量 

2.3  三个大问题

(1)一个参数既可以是const还可以是volatile吗?

        解释:一个例子是只读的状态寄存器。它是volatile因为它可能被意想不到地改变,是内部机制变化造成,而不是你的程序改变了它,而是操作系统把你的程序转成汇编语言时编译器另外加的汇编改变了它,它是const因为你写的程序部分不应该试图去修改它

(2)一个指针可以是volatile吗?

        解释:可以,尽管不常见,不如在中断服务子程序修改一个指向一个buffer的指针,防止编译器去优化,告诉编译器每次必须去内存中取值,而不是寄存器或缓存中

(3)多线程应用总被几个任务共享的变量

        解释:volatile对应的变量可能在你的程序本身不知道的情况下发生改变 。比如多线程的程序,共同访问的内存当中,多个程序都可以操纵这个变量 ,你自己的程序,是无法判定合适这个变量会发生变化  ,就像操作系统对线程的调度,内部调度机制在处理,所以有些变量程序本身是无法预测的


总结:   (1)编译器只会去看两次从i读数据的代码之间的代码没有对i进行过操作,但是在内部对数据处理过程是很复杂,volatile会改变代码生成的汇编代码,就是优化汇编代码,和不优化的汇编代码。如果i是一个寄存器变量或者表示一个端口数据,他可能被内部线程调度机制,突然使用了这个寄存器把这个寄存器改变了,有些汇编语句改变内存的值时,编译器并不知道,编译器看你的程序没有改变值,默认优化了,所以加了volatile就不会优化了

             (2)在vc6中,一般调试模式没有进行代码优化,所以这个关键字的作用看不出来 ,在嵌入式中不一样,




猜你喜欢

转载自blog.csdn.net/qq_40334837/article/details/80319419