2012-02-07 93 views
5

几天前我接受了一次采访,但仍然在寻找答案。 我想了解使用volatile关键字的意义。volatile&extern和有什么不一样?

找到下面的代码:两种不同的情况。

//project1 
//File1.c 

int abc;//Global variable 
/*And this variable is getting used in some other files too.*/ 
if(abc == 3) //Say 
{ 
    printf("abc == 3"); 
} 
else 
{ 
    printf("abc != 3"); 
} 
/*So if or else part will not be optimized 
because "abc" can not be predicted, 
the value can chage at any point of time */ 




//Project2 
//file1.c 

volatile int abc;//Global variable with volatile keyword 

/*And this variable is getting used in some other files too.*/ 

if(abc == 3) //Say 
{ 
    printf("abc == 3"); 
} 
else 
{ 
    printf("abc != 3"); 
} 
/*So if or else part will not be optimized 
because "abc" can not be predicted as it is declared as volatile, 
the value can chage at any point of time */ 

为什么我们应该使用volatile关键字呢?

+0

[静态全局变量和静态变量之间的区别是什么?](http:// stackoverflow。com/questions/346306/what-is-a-static-global-and-static-volatile-variable) – NPE 2012-02-07 09:05:57

+5

volatile和extern完全不相关。 – 2012-02-07 09:07:15

+0

@MarkByers:你说得对,但根据面试官的问题,上述两个都是一样的。那么为什么波动? – 2012-02-07 09:12:47

回答

5

正如Tony Delroy在其评论中解释的那样,externvolatile是完全不同的。


挥发性关键字保护您的变量从正在热映的优化。优化的变量对其他线程是不可见的,永远不会到达主内存。有时,如果不需要,编译器可以为even squeeze entirely一个变量。编译器根据你的源代码作为唯一的输入。有时候,有一些外部事件会改变你的变量值。例如,它可以是硬件设备或其他进程。

=>具体地说,编译器会禁用一些优化到这个变量,所以它可以像你想要的那样工作。


的extern是不是缓存内存VS。 Extern就是访问存在于其他对象文件中的变量。请参阅this short example哪种汇编代码是为extern访问生成的。 那些extern只要可能,变量在其自己的目标文件中被优化。保护与否不存在任何问题。

=>具体地,编译器指示外部参考需要对在链接时

+0

帧指针和外部无关。帧指针用于栈变量(自动存储类),extern是全局(静态存储类),不需要任何帧指针。 – Suma 2012-02-07 10:21:27

+0

该死的,我已经重新咀嚼,你说得对。我将删除我的回答的这部分内容 – Coren 2012-02-07 10:29:04

+1

extern的解释令人困惑。 – 2012-02-07 10:31:31

4

挥发性在声明或原型说总是加载/存储值从/到存储器无论本地来解决,静态extern这个vlaue(但在本地情况下它并不总是有意义的)。

还使用volatile关键字在常规来源是非典型的。它仅适用于将硬件寄存器映射到内存的硬件(如ARM架构中),以及内核/驱动程序开发的特殊情况。

如果您在GUI或电子商务代码中使用易失性,那么您可能是错误的...

+1

这个问题被标记为嵌入式,其中volatile非常典型。自动(局部)变量中的易失性是有意义的,例如用于延迟实现的循环计数器:'for(volatile unsigned int i = delay; i> 0; --i){}'。由于循环没有任何逻辑,优化器可以删除它,如果它不是'volatile'。 – Gauthier 2012-02-09 10:53:34

+1

它也可用于创建例如一个调试变量,您可以在该变量中写入程序从不读取的变量,并打算稍后在调试器中读取内容。 'static volatile uint8_t debug_buffer [64];'因为编译器发现保存的值不会被重用,所以它可以删除写操作。 'volatile'阻止了这一点。 – Gauthier 2012-02-09 10:59:08

+0

@ Gauthier谢谢你的建议!我记得有些嵌入式平台允许在内存访问某个地址时停止执行,因此您可以轻松跟踪任何可变值更改,而不会通过将其标记为volataile来降低执行性能。 – gavenkoa 2012-02-09 11:23:23

2

volatile通常是指一个或多个以下:

  1. 可变可以由另一个OS线程
  2. 执行的程序中的正常流可由信号被中断,并且信号处理程序得到改变可能会改变执行的可变
  3. 正常流正在运行一个循环,该变量被循环内读取,并且变量由点1或2
的装置改变

volatile表示在程序的整个生命周期中,变量有两个(或多个)读取R1和R2,并且在R1和R2之间发生的其他事件会将变量更改为正常执行流程之外的变量。


extern意味着变量已经某处别处定义和该程序重复使用的定义。

-1

本质上,volatile用于指示变量的值将被不同的线程修改。

声明挥发性Java变量是指:

The value of this variable will never be cached thread-locally: all reads and writes will go straight to "main memory"; 
Access to the variable acts as though it is enclosed in a synchronized block, synchronized on itself. 

的extern实质上意味着所有模块可以使用定义的变量。

1

我不完全同意以前的答案,所以这里是我的两分钱。

通过声明一个变量volatile,你告诉编译器它的值可以在任何时候改变,并且它不能对变量的值做任何假设,即使在两个连续的汇编指令中也是如此。结果任何变量的使用必须通过访问实际变量而不是缓存值来完成。

在您提供的代码中,abc之间没有任何行为差异,因为if()/ else只评估一次变量。是有区别但是如果你改变了其他人通过第二个如果,如:

if(abc == 3) 
{ 
    printf("abc == 3"); 
} 
if (abc != 3) 
{ 
    printf("abc != 3"); 
} 

如果农行不声明为volatile,编译器可以优化第二,如果和一个else语句来替换它,在后果ABC只会被读取和评估一次,这意味着第一次或第二次打印将被执行(但不是两者都是,也不是无)。

如果abc被声明为volatile(无论是局部的,全局的还是extern的),编译器会被迫评估abc两次,因为它的值可能在两者之间发生了变化。这意味着可以执行两个打印中的任何一个或两个或两个打印。

Extern完全不同。它所做的只是告诉编译器该变量已经在另一个文件中定义(其链接时将提供该地址)。如果编译器可以预测abc的值在两个if语句之间不会发生变化(编译器可能如何并不重要),那么它可能仍然会优化第二个if if into else并减少两个abc评估为1。

相关问题