gpt4 book ai didi

c - extern 和 volatile 的区别

转载 作者:太空宇宙 更新时间:2023-11-04 01:06:49 25 4
gpt4 key购买 nike

这个问题是关于 volatile 和 extern 变量之间的区别以及编译器优化。

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

外部测试.cpp:

short ExtGlobal;
void Fun();

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

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

源1.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 添加到外部变量,则会生成相同的汇编代码。两个不同线程中的 volatile 用法和两个不同函数中的外部变量用法是相同的。

最佳答案

询问 externvolatile 就像询问花生和 gorilla 。它们完全无关。

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

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

如果您想看到 volatile 导致生成不同的代码,请从变量中写入一系列读/写操作。

例如,在cygwin中用gcc -O1 -c编译这段代码,

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 的值,并且总是从内存中重新加载它。

关于c - extern 和 volatile 的区别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21297564/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com