volatile和extern有什么区别?

几天前我接受了采访,但仍然在寻找答案。 我想了解使用volatile关键字的意义。

找到下面的代码:两种不同的场景。

//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关键字呢?

正如Tony Delroy在其评论中解释的那样, 外部和不稳定是完全不同的。


Volatile关键字可以保护您的变量不被积极优化。 优化变量对于其他线程是不可见的,并且永远不会到达主存储器。 有时,如果不需要,编译器甚至可以完全压缩变量。 编译器将其猜测作为其唯一输入源代码。 有时,有一些外部事件可以改变您的变量值。 例如,它可以是硬件设备或其他过程。

=>具体地说,编译器禁用对此变量的一些优化,因此它可以按照您的意愿运行。


Extern不是关于缓存与内存。 Extern只是访问一个存在于其他目标文件中的变量。 请参阅为外部访问生成何种汇编代码的简短示例 。 这些extern变量尽可能在自己的目标文件中进行优化。 毫无疑问是要保护它。

=>具体地说,编译器指示需要在链接时解决的外部引用

声明或原型中的volatile表示始终从/向内存加载/存储值,无论是本地静态还是外部 (但在本地情况下并不总是有意义)。

在常规源中使用volatile关键字也是非常规的。 在内核/驱动程序开发的特殊情况下,它仅适用于将硬件寄存器映射到内存的硬件(如ARM体系结构中)。

如果你在GUI或电子商务代码中使用volatile ,你可能错了……

volatile通常表示以下一项或多项:

  1. 该变量可能会被另一个OS线程更改
  2. 程序中的正常执行流程可能会被信号中断,信号处理程序可能会更改变量
  3. 正常的执行流程正在运行循环,变量正在循环中读取,变量通过点1或2更改

volatile意味着在程序的整个生命周期中有两个(或更多)读取变量的R1和R2,而R1和R2之间发生的一些其他事件将改变正常执行流程之外的变量。


extern意味着变量已在其他地方定义,并且程序正在重用该定义。

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

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

在你提供的代码中,abc是global,extern或volatile之间没有行为差异,因为if()/ else只评估变量一次。 但是,如果您将else更改为秒,则会有所不同,如:

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

如果abc未被声明为volatile,则编译器可以优化第二个if并用else语句替换它,结果abc只会被读取和计算一次,这意味着第一个xor将执行第二个打印(但不是两个并且也是不是没有)。

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

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

从本质上讲,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本质上意味着所有模块都可以使用定义的变量。