C语言关键字volatile

简介:
C语言关键字volatile 
(总结网友经验给初学者) 
关键字volatile是什么声明? 
        将一个变量说明为volatile表示这个变量是“易变的”。如果一个变量会被其它引用改变,或在其它并行的 
任务中会被改变(例如中断服务程序),都要显式地说明为“volatile”,否则在编译器优化阶段会作出错误的判 
断,例如将这个变量读入寄存器以后,在没有对这个变量赋值以前,会一直使用寄存器中的值,而实际上这个变 
量的值可能已经被一个指针引用改变了,或者是在中断服务程序中被改变了,下面这个例子说明这种错误: 
        有一个变量T,在定时中断中每隔一个固定时间减一,然后在主程序中等待它减到0 
unsigned  char  T; 
void  T0_int(void)  interrupt 

    ... 
    T--; 
    ... 

void  main(void) 

    ... 
    T=10; 
    while  (T!=0);       
    ... 

正确的写法应该是将第一句改为: 
volatile  unsigned  char  T; 
*注:这个例子并不是针对特定的编译器,所以可能在有些编译器中能正确编译。但作为一个健壮的程序,一定要 
注意这一点,否则即使能得到正确结果,也会给程序移植或升级带来意想不到的问题。 



ARM编程:从“有关硬件寄存器、volatile、和不该发生的C编译器优化”谈volatile修饰的变量 
说到的问题的确是经常发生:  特别是在大系统中  类似的问题包括TC  BC等都出现过 
但是  反而是Keil较少出现-_-! 
其实  这个问题归根到底  就是volatile和变量优化的问题 
简单的说  C编译器  为了“偷懒”-_-b  在他认为你这个变量不会被修改的时候  就把相应的 
代码给“喀嚓”掉 
比如龙大的那个程序: 
void  IRQHandler(void) 

        u16  Int_Flag; 
        Int_Flag  REG_IF;                //  Read  the  interrupt  flags 
        SV32Bit++; 
        REG_SCCNT=0x5080; 
        REG_IF  Int_Flag;                //  Write  back  the  interrupt  flags 

编译器看Int_Flag  好像是个没有在函数内被修改的变量  就偷懒  认为这个变量是无用的 
类似与我们在keil中写个 
char  xxx; 
main 

        char  a; 
        xxx 
        xxx 
        while(1);     

他多半是会把这样的代码给优化掉——  也就是不编译出代码了 
这个时候  volatile  就有用了  简单的说  所有的标准  编译器  遇见volatile修饰的变量 
都认为这个变量的值是随机的  任何时候都是不同的  这样  每次对这样的变量的读出和写入 
都必须实际的去读写对应的地址  而不可以偷懒用:寄存器中的拷贝中的数据、可能数值一 
样的其他变量/常数等来“糊弄”系统  ^_^ 
比如我上面的那个main()编译器发现  xxx被读出然后无修改的重新写入  就懒得麻烦读写  索 
性优化掉了 
其实  volatile  在大多数的代码中  很少使用 
简单的说:他用来修饰那些可能会在你不知道的地方给修改的变量  比如 
 
1.定义成寄存器空间的变量   事实上  这个是他最大的一个用处!! 
比如ARM/C51/AVR/PIC等等的控制寄存器(SFR)空间  虽然  Keil用了一个sfr关键字来修饰寄 
存器:sfr  P0      0x80  …… 
但是  在标准C中  是必须使用这样的形式:#define  P0  *(volatile  unsighed  char  *)0x80 
 
2.会被中断修改的变量 有时候也需要加 不过这个不是项上一个那样是绝对的 
和编译器本身和你选择的优化等级等有关系 我的建议 在ADS中最好还是加上 Keil中就可以 
不用麻烦了  
 
回到龙大的那个问题上  龙大的问题虽然解决了  不过并不好  因为他把 
u16  定义成了  volatile  unsigned  short  这个对程序运行结果不会造成任何影响  不过带来 
了一个无法对变量优化的毛病 
事实上  这个问题的带来  是因龙大使用的那个  gba.h的一个bug 
我看到网上很多的gba.h的寄存器的定义  都吧寄存器们定义成: 
#define  REG_XXX  *(u16*)0x??????的形式 
这样  当龙大的IRQHandler程序进入后  编译器认为: 
REG_IF没有在函数里给修改  也没有给真正赋值     
a=x; 
x=a; 
这样  IRQHandler函数  在形式上  也就被认为和后面我写的那个main一样了 
这样的代码  编译器肯定是喀嚓的了 
那么  如果只把gba.h中的REG_IF的定义  加上volatile  修饰  而u16  依然是  unsighed  short 
呢? 

当然是一切都解决了……


本文转自feisky博客园博客,原文链接:http://www.cnblogs.com/feisky/archive/2009/01/08/1586362.html,如需转载请自行联系原作者


相关文章
|
2月前
|
存储 数据可视化 编译器
【C语言】union 关键字详解
联合体(`union`)是一种强大的数据结构,在C语言中具有广泛的应用。通过共享内存位置,联合体可以在不同时间存储不同类型的数据,从而节省内存。在嵌入式系统、硬件编程和协议解析等领域,联合体的使用尤为常见。理解和正确使用联合体可以使代码更加高效和灵活,特别是在内存受限的系统中。
117 3
【C语言】union 关键字详解
|
2月前
|
编译器 C语言
【C语言】extern 关键字详解
`extern` 关键字在C语言中用于跨文件共享变量和函数的声明。它允许你在一个文件中声明变量或函数,而在其他文件中定义和使用它们。理解 `extern` 的使用可以帮助你组织和管理大型项目的代码。
217 3
|
2月前
|
C语言
【C语言】break 关键字详解
- `break` 关键字用于提前退出循环体或 `switch` 语句的执行。 - 在 `for`、`while` 和 `do-while` 循环中,`break` 可以帮助程序在满足特定条件时退出循环。 - 在 `switch` 语句中,`break` 用于终止 `case` 代码块的执行,避免代码“穿透”到下一个 `case`。 - 注意 `break` 只会退出最内层的循环或 `switch` 语句,确保在嵌套结构中正确使用 `break` 以避免意外的控制流行为。
147 2
|
2月前
|
传感器 安全 编译器
【C语言】enum 关键字详解
`enum`关键字在C语言中提供了一种简洁而高效的方法来定义一组相关的常量。通过使用枚举,可以提高代码的可读性、可维护性,并减少错误的发生。在实际应用中,枚举广泛用于表示状态、命令、错误码等,为开发者提供了更清晰的代码结构和更方便的调试手段。通过合理使用枚举,可以编写出更高质量、更易维护的C语言程序。
146 2
|
2月前
|
缓存 安全 编译器
【C语言】volatile 关键字详解
`volatile` 关键字在 C 语言中用于防止编译器对某些变量进行优化,确保每次访问该变量时都直接从内存中读取最新的值。它主要用于处理硬件寄存器和多线程中的共享变量。然而,`volatile` 不保证操作的原子性和顺序,因此在多线程环境中,仍然需要适当的同步机制来确保线程安全。
83 2
|
2月前
|
存储 编译器 程序员
【C语言】auto 关键字详解
`auto` 关键字用于声明局部变量的自动存储类,其作用主要体现在变量的生命周期上。尽管现代C语言中 `auto` 的使用较少,理解其历史背景和作用对于掌握C语言的存储类及变量管理仍然很重要。局部变量默认即为 `auto` 类型,因此在实际编程中,通常不需要显式声明 `auto`。了解 `auto` 关键字有助于更好地理解C语言的存储类及其在不同场景中的应用。
91 1
|
2月前
|
C语言
【C语言】continue 关键字详解
`continue` 关键字在 C 语言中用于跳过当前循环中的剩余代码,并立即开始下一次迭代。它主要用于控制循环中的流程,使程序在满足特定条件时跳过某些代码。
155 1
【C语言】continue 关键字详解
|
2月前
|
存储 C语言
【C语言】static 关键字详解
`static` 关键字在C语言中用于控制变量和函数的作用域和生命周期。它可以用于局部变量、全局变量和函数,具有不同的效果。理解 `static` 关键字的用法有助于封装和管理代码,提高代码的可维护性和可靠性。
89 3
|
2月前
|
C语言
【C语言】return 关键字详解 -《回家的诱惑 ! 》
`return` 关键字在 C 语言中用于终止函数的执行,并将控制权返回给调用者。根据函数的类型,`return` 还可以返回一个值。它是函数控制流中的重要组成部分。
110 2
|
2月前
|
C语言
【C语言】sizeof 关键字详解
`sizeof` 关键字在C语言中用于计算数据类型或变量在内存中占用的字节数。它是一个编译时操作符,对性能没有影响。`sizeof` 可以用于基本数据类型、数组、结构体、指针等,了解和正确使用 `sizeof` 对于内存管理和调试程序非常重要。
100 2

热门文章

最新文章