我一般都了解和理解易失性变量和优化的目的(嗯,我想是的!)。这个问题专门涉及如果在声明变量的模块外部访问变量会发生什么情况。
在以下情况下,如果在bar.c内部调用了funcThatWaits
,则可以对其进行优化,而不必在每次循环迭代中获取sTheVar
的值。
但是,当从外部调用GetTheVar
时是否可以应用相同的优化方法,或者该函数调用可以确保每次循环迭代都始终读取sTheVar
?
我并不是说这是好的代码或惯例,而是出于问题的例子。
bar.h
int GetTheVar(void);
bar.c
static /*volatile*/ int sTheVar;
int GetTheVar(void)
{
return sTheVar;
}
static void someISROrFuncCalledFromAnotherThread(void)
{
sTheVar = 1;
}
foo.c
#include "bar.h"
void funcThatWaits(void)
{
while(GetTheVar() != 1) {}
}
答案 0 :(得分:1)
在外部调用
GetTheVar
时是否可以应用相同的优化方法,或者该函数调用确保每次循环迭代时始终读取sTheVar
?
可以应用相同的优化。例如,如果您使用的是LTO(链接时间优化),则编译器会了解有关GetTheVar
的所有信息,并且很可能会确定funcThatWaits
是一个无限循环(顺便说一下,它将是UB)
答案 1 :(得分:0)
函数调用不会得到优化,因为调用者都知道,被调用的函数可能取决于某种外生状态。
我使用gcc编译了以下三个文件:
foo.c
#include "bar.h"
void funcThatWaits(void) {
while ( getVar() != 1 );
}
bar.c
#include "foo.h"
static int theVar;
int getTheVar(void) {
return theVar;
}
void theFunc(void) {
funcThatWaits();
}
test.c
#include "bar.h"
int main() {
theFunc();
return 0;
}
将这三个代码编译为a.out并运行objdump -d a.out
,结果如下:
00000000000005fa <main>:
5fa: 55 push %rbp
5fb: 48 89 e5 mov %rsp,%rbp
5fe: e8 25 00 00 00 callq 628 <theFunc>
603: b8 00 00 00 00 mov $0x0,%eax
608: 5d pop %rbp
609: c3 retq
000000000000060a <funcThatWaits>:
60a: 55 push %rbp
60b: 48 89 e5 mov %rsp,%rbp
60e: 90 nop
60f: e8 08 00 00 00 callq 61c <getTheVar>
614: 83 f8 01 cmp $0x1,%eax
617: 75 f6 jne 60f <funcThatWaits+0x5>
619: 90 nop
61a: 5d pop %rbp
61b: c3 retq
000000000000061c <getTheVar>:
61c: 55 push %rbp
61d: 48 89 e5 mov %rsp,%rbp
620: 8b 05 ee 09 20 00 mov 0x2009ee(%rip),%eax # 201014 <theVar>
626: 5d pop %rbp
627: c3 retq
0000000000000628 <theFunc>:
628: 55 push %rbp
629: 48 89 e5 mov %rsp,%rbp
62c: e8 d9 ff ff ff callq 60a <funcThatWaits>
631: 90 nop
632: 5d pop %rbp
633: c3 retq
634: 66 2e 0f 1f 84 00 00 nopw %cs:0x0(%rax,%rax,1)
63b: 00 00 00
63e: 66 90 xchg %ax,%ax