编译器如何知道每个静态变量调用一次函数?

时间:2010-05-06 21:57:46

标签: c++ static

E.g

 foo1() {
     static const char* str = foo2();

 }

 const char * foo2 () {

     ...
 }

编译器如何确保它只调用一次foo2。

4 个答案:

答案 0 :(得分:4)

foo2在程序初始化时调用,就在main()之前。

编辑:这是错误!我认为这是正常静态初始化的工作方式。但在这种情况下,它们在函数开始时被调用一次。

它必须使用某种静态布尔值。是的。至少在gcc中,这个:

int test2()
{
    static int bla = test();
}

编译为:

 8048616: b8 30 a0 04 08        mov    $0x804a030,%eax
 804861b: 0f b6 00              movzbl (%eax),%eax
 804861e: 84 c0                 test   %al,%al
 8048620: 75 52                 jne    8048674 <_Z5test2v+0x67>
 ...
 804863c: e8 b3 ff ff ff        call   80485f4 <_Z4testv>
 ...
 8048674: 83 c4 1c              add    $0x1c,%esp
 8048677: 5b                    pop    %ebx
 8048678: 5e                    pop    %esi
 8048679: 5f                    pop    %edi
 804867a: 5d                    pop    %ebp
 804867b: c3                    ret    

因此它使用隐藏的,函数特定的布尔值($ 0x804a030)+一些魔法来防止异常和多个线程一次调用它。

答案 1 :(得分:4)

没有一个编译器。 gcc可能会这样做,视觉工作室可能会做另一种方式。

从概念上说,有一个隐藏的静态布尔值,编译器正在生成一个if语句。

答案 2 :(得分:0)

函数中的静态在第一次被命中时被调用。例如:

#include <stdio.h>

class Thing
{
    public:
    Thing()
    {
        printf ("initializing thing\n");
    }
};

int foo()
{
    static Thing *thing = new Thing;
    printf ("done\n");
}

int main()
{
    printf ("calling foo:\n");
    foo();
    printf ("foo returned\n");

    printf ("calling foo:\n");
    foo();
    printf ("foo returned\n");
}

给出这个:

calling foo:
initializing thing
done
foo returned
calling foo:
done
foo returned

答案 3 :(得分:0)

编译器可能会编译以下内容:

void foo1() {
    static const char* str = foo2();
}

好像它写成:

void foo1() {
    static int __str_initialized = 0;
    static const char* str;

    if (__str_initialized == 0) {
        str = foo2();
        __str_initialized = 1;
    }
}

请注意,__str_initialized的初始化可以作为将数据段初始化为0的正常部分发生,因此不需要在那里发生任何特殊情况。

另请注意,这是线程安全,并且一般来说编译器执行的静态变量初始化将不是线程安全的(也不需要通过标准 - 我不确定什么编译器可以使这个线程安全。)