从另一个模块访问的C / C ++易失变量

时间:2020-06-15 04:14:47

标签: c volatile

我一般都了解和理解易失性变量和优化的目的(嗯,我想是的!)。这个问题专门涉及如果在声明变量的模块外部访问变量会发生什么情况。

在以下情况下,如果在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) {}
}

2 个答案:

答案 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