extern和volatile之间的区别

时间:2014-01-23 01:26:15

标签: c

这个问题考虑了volatile和extern变量之间的区别以及编译器优化。

在主文件中定义的一个外部变量,并在另一个源文件中使用,如下所示:

ExternTest.cpp:

short ExtGlobal;
void Fun();

int _tmain(int argc, _TCHAR* argv[])
{

    ExtGlobal=1000;
    while (ExtGlobal < 2000)
    {
        Fun();
    }
    return 0;
}

Source1.cpp:

extern short ExtGlobal;

void Fun()
{
    ExtGlobal++;
}

在vs2012中为此生成的程序集如下:

用于访问外部变量的ExternTest.cpp程序集

ExtGlobal=1000;
013913EE  mov         eax,3E8h  
013913F3  mov         word ptr ds:[01398130h],ax  

while (ExtGlobal < 2000)
013913F9  movsx       eax,word ptr ds:[1398130h]  
01391400  cmp         eax,7D0h  
01391405  jge         wmain+3Eh (0139140Eh) 

Source.cpp程序集,用于修改外部变量

ExtGlobal++;
0139145E  mov         ax,word ptr ds:[01398130h]  
01391464  add         ax,1  
01391468  mov         word ptr ds:[01398130h],ax  

从上面的程序集中,while循环中对变量“ExtGlobal”的每次访问都从相应的地址中读取值。如果我向外部变量添加volatile,则生成相同的汇编代码。两个不同线程中的易失性使用和两个不同函数中的外部变量使用是相同的。

1 个答案:

答案 0 :(得分:5)

询问externvolatile就像询问花生和大猩猩一样。他们完全不相关。

extern只是用来告诉编译器,“嘿,不要指望在这个C文件中找到这个符号的定义。让链接器在最后修复它。”

volatile基本上告诉编译器,“永远不要相信这个变量的值。即使你只是将一个值从寄存器存储到该内存位置,也不要重复使用寄存器中的值 - 确保从内存中重新读取它。“

如果要查看volatile导致生成不同的代码,请从变量中写入一系列读/写。

例如,使用gcc -O1 -c

在cygwin中编译此代码
int i;

void foo() {
    i = 4;

    i += 2;

    i -= 1;
}

生成以下程序集:

_foo proc near
mov     dword ptr ds:_i, 5
retn
_foo endp

请注意,编译器知道结果是什么,所以它只是继续并优化它。

现在,将volatile添加到int i会生成以下内容:

public _foo
_foo proc near
mov     dword ptr ds:_i, 4

mov     eax, dword ptr ds:_i
add     eax, 2
mov     dword ptr ds:_i, eax

mov     eax, dword ptr ds:_i
sub     eax, 1
mov     dword ptr ds:_i, eax

retn
_foo endp

编译器永远不会信任i的值,而总是从内存中重新加载它。