Откуда компилятор знает, что нужно вызывать функцию один раз для каждой статической переменной? - PullRequest
4 голосов
/ 07 мая 2010

Eg

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

 }

 const char * foo2 () {

     ...
 }

Как компилятор удостоверяется, что он вызывает foo2 только один раз.

Ответы [ 4 ]

4 голосов
/ 07 мая 2010

Нет одного компилятора. gcc может сделать это одним способом, Visual Studio может сделать это другим способом.

Концептуально , существует скрытое статическое логическое значение, и компилятор создает оператор if.

4 голосов
/ 07 мая 2010

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) + некоторую магию для защиты от исключений и несколько потоков, вызывающих его одновременно.

0 голосов
/ 07 мая 2010

Компилятор может скомпилировать следующее:

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, поэтому ничего особенного там не должно происходить.

Также обратите внимание, что это не поточно-ориентированный, и, вообще говоря, инициализация статической переменной, которую выполняет компилятор, не будет поточно-ориентированной (и при этом не требуется соблюдения стандарта - я не уверен компиляторы могут сделать этот потокобезопасным).

0 голосов
/ 07 мая 2010

Статика в функции вызывается при первом обращении к ней. Например:

#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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...