c语言中volatile关键字
一篇文章带你了解C语言中volatile关键字

⼀篇⽂章带你了解C语⾔中volatile关键字⽬录C语⾔中volatile关键字总结C语⾔中volatile关键字volatile关键字是C语⾔中⾮常冷门的关键字,因为⽤到这个关键字的场景并不多。
当不⽤这个关键字的时候,CPU可能会对我们的代码做⼀定的优化:内存中的数据要放⼊CPU中进⾏运算或控制,⽽这个数据的值是被放⼊寄存器中,然后再将寄存器中的数据进⾏运算或控制的,对于⼀个死循环int flag=1;while(flag);来说;如果进⾏优化,则下次循环则不需要再次将flag内存中的值放⼊寄存器中,⽽是直接使⽤寄存器中已有的值进⾏循环;如果不进⾏优化,则下次还需要将flag内存中的值放⼊寄存器中,然后使⽤寄存器中的数据。
总结起来就是,遇到这个关键字声明的变量,编译器对访问该变量的代码就不再进⾏优化,从⽽可以提供对其地址的稳定访问;如果不使⽤valatile,则编译器将对所声明的语句进⾏优化。
这两种情况在单线程的情况下区别不⼤,但是在多线程的情况下可能会有其他逻辑将flag修改为0,如果进⾏优化,则死循环不会停下来。
所以volatile的作⽤就是让变量不要被CPU优化,达到稳定访问内存的⽬的。
⽐如下⾯的代码:我们在gcc下使⽤命令gcc test.c -O2 -g将代码进⾏优化,然后⽤命令objdump -S -d a.out > a.s将优化后的汇编代码放⼊a.s⽂件中,再⽤vim a.s查看a.s⽂件:程序会⼀直在这⼀句代码中死循环:加⼊volatile后:再⽤相同的命令查看a.s⽂件:可以看到每次循环都会读取pass的数据。
结论: volatile 忽略编译器的优化,保持内存可见性。
另外,const和volatile是不冲突的:const volatile int a = 10;const关键字要求变量a不能直接被写⼊,⽽volatile关键字要求每次读取数据的时候,都要从a所在的内存中读取,并不会改变变量a的值。
c语言 volatile的原理

c语言 volatile的原理
C语言中的volatile关键字用于告诉编译器不要对被声明为volatile的变量进行优化,因为这些变量的值可能会在程序的控制之外被改变。
volatile的原理涉及编译器优化和内存访问的问题。
当一个变量被声明为volatile时,编译器会生成对该变量的每次访问代码,以确保对该变量的读写操作不会被优化掉。
这是因为volatile变量的值可能会在程序的执行过程中被外部因素改变,比如硬件中断、多线程环境下的共享变量等。
如果编译器对volatile 变量的读写操作进行优化,可能导致程序出现意外的行为。
另外,volatile还可以用于指针类型。
当一个指针被声明为volatile时,意味着该指针所指向的内存区域的内容可能会在程序的控制之外被修改,因此编译器不应该对通过该指针进行的读写操作进行优化。
在多线程编程中,volatile还可以用于确保线程之间对共享变量的可见性。
在这种情况下,volatile可以告诉编译器不要对共享变量的读写操作进行重排序,以确保线程能够正确地看到其他线程对共享变量的修改。
总之,volatile关键字的原理涉及编译器优化和内存访问的问题,它告诉编译器不要对声明为volatile的变量进行优化,以确保这些变量的读写操作不会被意外地优化掉,从而保证程序的正确性和可靠性。
C语言中volatile的作用和使用方法

C语⾔中volatile的作⽤和使⽤⽅法 在程序设计中,尤其是在C语⾔、C++、C#和Java语⾔中,使⽤volatile关键字声明的变量或对象通常具有与优化、多线程相关的特殊属性。
通常,volatile关键字⽤来阻⽌(伪)编译器认为的⽆法“被代码本⾝”改变的代码(变量/对象)进⾏优化。
如在C语⾔中,volatile关键字可以⽤来提醒编译器它后⾯所定义的变量随时有可能改变,因此编译后的程序每次需要存储或读取这个变量的时候,都会直接从变量地址中读取数据。
如果没有volatile关键字,则编译器可能优化读取和存储,可能暂时使⽤寄存器中的值,如果这个变量由别的程序更新了的话,将出现不⼀致的现象。
举个栗⼦:在这⾥例⼦中,代码将foo的值设置为0。
然后开始不断地它的值直到它变成255:static int foo;void bar(void) {foo = 0;while (foo != 255);}⼀个会提⽰没有代码能修改foo的值,并假设它永远都只会是0.因此编译器将⽤类似下列的替换函数体:void bar_optimized(void) {foo = 0;while (true);}但是,foo可能指向⼀个随时都能被计算机系统其他部分修改的地址,例如⼀个连接到的设备的,上⾯的代码永远检测不到这样的修改。
如果不使⽤volatile关键字,编译器将假设当前程序是系统中唯⼀能改变这个值部分(这是到⽬前为⽌最⼴泛的⼀种情况)。
为了阻⽌编译器像上⾯那样优化代码,需要使⽤volatile关键字:static volatile int foo;void bar (void) {foo = 0;while (foo != 255);}这样修改以后循环条件就不会被优化掉,当值改变的时候系统将会检测到。
总结: 优点:防⽌编译器对代码优化,变量值是直接从变量地址中读取和存储的。
缺点:这种使⽤过多会导致代码⼗分庞⼤。
volatile在c语言中的用法

volatile在c语言中的用法c语言是一种常用的面向对象的编程语言,在c语言中,volatile 关键字是一种有用的功能,可以用来表明某个内存单元的值可能会受外部因素的影响,而不受编译器优化的影响,从而可以保证值的正确性。
它是使用c语言开发复杂软件系统时不可缺少的功能。
一、什么是volatile?volatile关键字表明被修饰的变量是一个易变的存储单元,它不会被编译器进行优化,并且可能会受外部因素的影响,不会被改变,而值也将保留在它的存储位置中。
二、volatile的用途1. 保护共享变量如果在多个线程之间共享一个变量,使用volatile关键字可以保护这个变量的值不会被程序员或编译器优化错误地更改。
2. 保护I/O操作当多个线程访问内存中的I/O端口时,使用volatile关键字可以确保I/O操作的原子性,避免程序出现异常。
3.保变量的更新当多个线程对一个变量进行更新操作时,使用volatile关键字可以确保变量的值在线程间断开之前一定会被正确更新。
4.省CPU资源volatile关键字可以避免编译器对变量的不必要的操作,从而节省CPU的资源消耗。
三、volatile的局限volatile关键字只能保证变量的可见性,但无法保证变量的原子性,因此在使用volatile时,仍需要注意线程安全问题。
当多个线程同时操作一个volatile变量时,可能会出现不可预料的结果,因此在使用volatile关键字时,需要借助其他的技术手段,来保证变量的原子性。
四、总结volatile关键字在c语言中是一个非常有用的功能,可以用来实现变量的可见性,确保各个线程对变量的更新操作是同步处理的,从而避免出现竞争条件。
但是,由于volatile关键字只能保证变量的可见性,所以在处理多线程操作时,仍需要注意线程安全问题,使用其他技术手段,来保证变量的原子性。
C语言中的volatile

C语⾔中的volatile1.volatile有什么含义?有什么⽤法?官⽅定义是:⼀个变量也许会被后台程序改变。
关键字volatile与const绝对独⽴。
它指⽰⼀个变量也许会被某种⽅式修改,这种⽅式按照正常程序流程分析是⽆法预知的(例如,⼀个变量也许会被⼀个中断服务程序所修改)。
这个关键字使⽤以下语法定义:volatile data-defiinition;注:变量如果加了voletile修饰,则会从内存中重新装载内容,⽽不是直接从寄存器中拷贝内容。
2.编译器的优化在本次线程内,当读取⼀个变量时,为了提⾼读取速度,编译器进⾏优化时有时会先把变量读取到⼀个寄存器中;以后,再读取变量值时,就直接从寄存器中读取;当变量值在本线程⾥改变时,会同时把变量的新值copy到该寄存器中,以保持⼀致。
当变量因别的线程值发⽣改变,上⾯寄存器的值不会相应改变,从⽽造成应⽤程序读取的值和实际的变量值不⼀致。
3.常见的问题(1)说明关键字volatile有什么含意,并给出例⼦。
volatile表⽰被修饰的符号是易变的。
告诉编译器不要随便优化我的代码!!*⼀个硬件寄存器*中断中⽤到的变量*线程之间共享变量volatile int a = 10;while((a & 0x01) == 0);#define P_UART_STATUS ((const volatile unsigned int *)0x88000000);// volatile表⽰硬件会修改这个寄存器的内容// const表⽰该寄存器只读,写⽆意义(2)⼀个定义为volatile的变量是说这变量可能会被意想不到地改变,这样,编译器就不会去假设这个变量的值了。
精确地说就是,优化器在⽤到这个变量时必须每次都⼩⼼地重新读取这个变量的值,⽽不是使⽤保存在寄存器⾥的备份。
下⾯是volatile变量的⼏个例⼦:1). 并⾏设备的硬件寄存器(如:状态寄存器)2). ⼀个中断服务⼦程序中会访问到的⾮⾃动变量(Non-automatic variables)3). 多线程应⽤中被⼏个任务共享的变量(3)1). ⼀个参数既可以是const还可以是volatile吗?解释为什么。
嵌入式软件开发岗位招聘笔试题及解答(某大型国企)

招聘嵌入式软件开发岗位笔试题及解答(某大型国企)(答案在后面)一、单项选择题(本大题有10小题,每小题2分,共20分)1、在C语言中,volatile关键字的主要作用是什么?A. 使变量成为全局变量B. 告诉编译器该变量可能会被外部因素改变,从而阻止优化C. 使变量成为常量D. 加快变量访问速度2、关于ARM架构处理器,以下哪个描述是正确的?A. ARM架构处理器仅支持32位指令集B. 所有的ARM处理器都支持Thumb-2技术C. ARM处理器采用的是RISC设计理念D. ARM处理器不能运行Linux操作系统3、嵌入式软件开发岗位笔试题及解答(某大型国企)一、单项选择题(每题2分,共20分)3、以下哪个不是嵌入式系统设计中常用的实时操作系统(RTOS)?A. VxWorksB. LinuxC. FreeRTOSD. Windows CE4、在嵌入式软件开发中,以下哪个概念不是用于描述硬件和软件之间接口的标准?A. 总线协议B. 寄存器映射C. 驱动程序D. API5、在ARM架构中,哪个寄存器通常被用作链接寄存器来保存子程序返回地址?A. R0B. R13 (SP)C. R14 (LR)D. R15 (PC)6、关于嵌入式系统的实时性,下列说法正确的是:A. 实时系统必须保证所有任务都能在指定的时间内完成B. 实时系统仅关注任务的平均响应时间C. 软实时系统对响应时间的要求比硬实时系统更加严格D. 实时系统中,任务的优先级可以根据任务的紧迫程度动态调整7、以下哪个协议不属于嵌入式系统中常用的网络通信协议?A. TCP/IPB. CAN(Controller Area Network)C. BluetoothD. SPI(Serial Peripheral Interface)8、在嵌入式软件开发中,以下哪个概念通常用来描述硬件和软件之间的接口?A. 驱动程序B. 硬件抽象层(HAL)C. 用户界面(UI)D. 操作系统内核9、在嵌入式系统开发过程中,以下哪种编程语言通常被认为最适合用于硬件抽象层(HAL)的开发?A. JavaB. C++C. CD. Python 10、以下关于ARM架构的描述,哪一项是正确的?A. ARM架构是一种RISC(精简指令集计算机)架构。
volatile的用法及原理

volatile的用法及原理Volatile的用法及原理Volatile是C语言中的一个关键字,用于告诉编译器该变量是易变的,需要在每次访问时都从内存中读取,而不是从寄存器中读取。
这个关键字通常用于多线程编程中,以确保线程之间的可见性和一致性。
在多线程编程中,由于线程之间的执行顺序是不确定的,因此可能会出现一个线程修改了某个变量的值,但是另一个线程并没有及时地看到这个变化,导致程序出现错误。
这种情况被称为“竞态条件”,可以通过使用Volatile关键字来避免。
Volatile的原理是告诉编译器不要对该变量进行优化,每次访问都要从内存中读取最新的值。
这样可以确保多个线程之间对该变量的访问是同步的,避免了竞态条件的出现。
在C语言中,Volatile关键字可以用于变量、指针和结构体等数据类型。
例如,下面的代码定义了一个Volatile变量:```volatile int count = 0;```在多线程编程中,如果一个线程需要修改count的值,可以使用原子操作来保证线程安全。
例如,下面的代码使用了GCC提供的原子操作来实现对count的自增操作:```__sync_fetch_and_add(&count, 1);```这个操作会保证在多线程环境下,对count的自增操作是原子的,不会出现竞态条件。
需要注意的是,Volatile关键字只能保证对单个变量的访问是同步的,不能保证多个变量之间的同步。
如果需要保证多个变量之间的同步,可以使用互斥锁、条件变量等同步机制。
Volatile关键字是多线程编程中非常重要的一个关键字,可以保证线程之间的可见性和一致性,避免竞态条件的出现。
在使用Volatile 关键字时,需要注意其原理和使用方法,以确保程序的正确性和性能。
对C语言的volatile关键字的理解

对C语⾔的volatile关键字的理解volatile在英语的意思是:挥发性的, 不稳定的, 易变的. 在编程中不是是很容易被理解的它, 加上平常很少被⽤到, 再加上它更多地被⽤于硬件编程⽅⾯,所以就更加让⼀些⼈琢磨不透了.总之, 作为⼀个变量类型修饰符, volatile的作⽤就是被设计⽤来修饰被不同线程访问和修改的变量. 在原⼦操作中同样会⽤到. 如果没有它, 很有可能使得编程写的多线程程序出现不可预期的错误, 也可能因为编译器的各种优化⽽导致编译后的结果表达了不同的意思, 使得程序出现难以发现的错误.被volatile修饰的变量是说这个变量可能会被意想不到地被改变, 这样, 编译器就不会在编译会访问该变量的语句的时候, 依然使⽤保存在某个寄存器的值来加快速度, 取⽽代之的是, 每次都从该变量的原始地址处重新读取该变量的值, 这样就能使得取到的值总是是"最新"的, 真正意义上的最新. 区别在于:如果编译器在编译涉及到访问某个变量的值的时候, 它会把被频繁访问的变量保存到CPU的寄存器中供复⽤, 以加快再次访问变量的速度. 但是, 该值是从CPU的寄存器中取出的, 它虽然是最原始的值, 但如果在其它时间, 其它地点的程序如果修改了该变量的值, 那么编译器拿到的值就是⼀个"过时"的值, 这样就会出现错误. 其它时间可以是CPU的线程调度, 其它地点可以是另⼀个线程的代码.下⾯看⼀点C语⾔例⼦.int main(void){int i;i = 1;i = 2;return i;}在Debug模式(⽆任何优化)下, ⽣成的32位汇编代码(省略其它代码)为:; i = 1mov dword ptr[ebp-4],1; i = 2mov dword ptr[ebp-4],2; return imov eax,dword ptr[ebp-4]ret可见, 对i的每次赋值都会产⽣⼀条汇编语句来对应, 这完全同C程序意思.⽽当⽣成模式改成Release(优化被打开; 可能需要在项⽬设置中钩上"⽣成调试信息")后,对应如下(省略其它代码):mov eax,2ret可见, 多余的赋值代码都被优化掉了, 这就是编译器的优化措施.好的, 我们再把源代码改成如下形式:int main(void){volatile int i;i = 1;i = 2;return i;}修改后, Debug⽣成的汇编代码没有变化, 但Release⽣成的代码却变成了:push ecxmov dword ptr[esp],1mov dword ptr[esp],2mov eax,dword ptr[esp]pop ecx可见, 加了volatile后, 就算打开优化, 编译器也不会作优化, 每次取值都是重新取值, 虽然在这⾥所有语⾔直接⼀条return 2;就可以代替, 但编译器却没有那样做~另⼀个典型的例⼦, 可能很多⼈⽤于延时,测试速度:int i;for(i=0; i<10000; i++);。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
volatile关键字是一种类型修饰符,用它声明的类型变量表示可以被某些编译器未知的因素更改。
用volatile关键字声明的变量i每一次被访问时,执行部件都会从i相应的内存单元中取出i 的值。
没有用volatile关键字声明的变量i在被访问的时候可能直接从cpu的寄存器中取值(因为之前i被访问过,也就是说之前就从内存中取出i的值保存到某个寄存器中),之所以直接从寄存器中取值,而不去内存中取值,是因为编译器优化代码的结果(访问cpu寄存器比访问ram快的多)。
以上两种情况的区别在于被编译成汇编代码之后,两者是不一样的。
之所以这样做是因为变量i可能会经常变化,保证对特殊地址的稳定访问。
=====以下为转载======
volatile关键字是一种类型修饰符,用它声明的类型变量表示可以被某些编译器未知的因素更改
,比如:操作系统、硬件或者其它线程等。
遇到这个关键字声明的变量,编译器对访问该变量的
代码就不再进行优化,从而可以提供对特殊地址的稳定访问。
使用该关键字的例子如下:
int volatile nVint;
当要求使用volatile 声明的变量的值的时候,系统总是重新从它所在的内存读取数据,即
使它前面的指令刚刚从该处读取过数据。
而且读取的数据立刻被保存。
例如:
volatile int i=10;
int a = i;
...
//其他代码,并未明确告诉编译器,对i进行过操作
int b = i;
volatile 指出i是随时可能发生变化的,每次使用它的时候必须从i的地址中读取,因而编
译器生成的汇编代码会重新从i的地址读取数据放在b中。
而优化做法是,由于编译器发现两次从
i读数据的代码之间的代码没有对i进行过操作,它会自动把上次读的数据放在b中。
而不是重新
从i里面读。
这样以来,如果i是一个寄存器变量或者表示一个端口数据就容易出错,所以说vola
tile可以保证对特殊地址的稳定访问。
注意,在vc6中,一般调试模式没有进行代码优化,所以这个关键字的作用看不出来。
下面
通过插入汇编代码,测试有无volatile关键字,对程序最终代码的影响:
首先,用classwizard建一个win32 console工程,插入一个voltest.cpp文件,输入下面的
代码:
#i nclude <stdio.h>
void main()
{
int i=10;
int a = i;
printf("i= %d\n",a);
//下面汇编语句的作用就是改变内存中i的值,但是又不让编译器知道
__asm {
mov dword ptr [ebp-4], 20h
}
int b = i;
printf("i= %d\n",b);
}
然后,在调试版本模式运行程序,输出结果如下:
i = 10
i = 32
然后,在release版本模式运行程序,输出结果如下:
i = 10
i = 10
输出的结果明显表明,release模式下,编译器对代码进行了优化,第二次没有输出正确的i 值。
下面,我们把i的声明加上volatile关键字,看看有什么变化:
#i nclude <stdio.h>
void main()
{
volatile int i=10;
int a = i;
printf("i= %d\n",a);
__asm {
mov dword ptr [ebp-4], 20h
}
int b = i;
printf("i= %d\n",b);
}
分别在调试版本和release版本运行程序,输出都是:
i = 10
i = 32
这说明这个关键字发挥了它的作用!。