Quando as variables ​​estáticas e globais são inicializadas?

Em C++ eu sei que objects static e global são construídos antes da function main . Mas como você sabe, em C , não existe tal initialization procedure antes do main .

Por exemplo, no meu código:

 int global_int1 = 5; int global_int2; static int static_int1 = 4; static int static_int2; 
  • Quando essas quatro variables ​​são inicializadas ?
  • Onde valores para boot como 5 e 4 são armazenados durante a compilation? Como gerenciá-los quando boot?

EDITAR:
Esclarecimento da 2ª questão.

  • No meu código eu uso 5 para inicializar global_int1 , então como o compilador pode atribuir 5 a global_int ? Por exemplo, talvez o compilador primeiro armazene o valor 5 em algum lugar (ou seja, uma tabela) e obtenha esse valor quando a boot começar.
  • Quanto ao “Como gerenciá-los quando boot?”, É realmente vago e eu mesmo não como interpretar ainda. Às vezes, não é fácil explicar uma questão. Negligencie isto desde que eu ainda não dominei a pergunta completamente.

Por objects estáticos e globais, presumo que você queira dizer objects com vida útil estática definida no escopo do namespace. Quando tais objects são definidos com escopo local, as regras são ligeiramente diferentes.

Formalmente, o C ++ inicializa essas variables ​​em três fases: 1. Inicialização zero 2. Inicialização estática 3. Inicialização dinâmica A linguagem também distingue entre variables ​​que requerem boot dinâmica e aquelas que requerem boot estática: todos os objects estáticos (objects com vida útil estática) são primeiro zero inicializado, os objects com boot estática são inicializados e, em seguida, ocorre a boot dinâmica.

Como uma primeira aproximação simples, a boot dinâmica significa que algum código deve ser executado; Normalmente, a boot estática não. Portanto:

 extern int f(); int g1 = 42; // static initialization int g2 = f(); // dynamic initialization 

Outra aproximação seria que a boot estática é o que C suporta (para variables ​​com tempo de vida estático), todo o resto dynamic.

Como o compilador faz isso, é claro, na boot, mas em sistemas baseados em disco, onde o executável é carregado na memory a partir do disco, os valores para boot estática fazem parte da imagem no disco e são carregados diretamente pelo sistema. O disco. Em um sistema Unix clássico, as variables ​​globais seriam divididas em três “segmentos”:

texto:
O código, carregado em uma área protegida contra gravação. Variáveis ​​estáticas com tipos `const` também seriam colocadas aqui.
dados:
Variáveis ​​estáticas com inicializadores estáticos.
bss:
Variáveis ​​estáticas com sem inicializador (C e C ++) ou com boot dinâmica (C ++). O executável não contém imagem para este segmento, e o sistema simplesmente define tudo como `0` antes de iniciar seu código.

Eu suspeito que muitos sistemas modernos ainda usam algo similar.

EDITAR:

Uma observação adicional: o acima refere-se a C ++ 03. Para programas existentes, o C ++ 11 provavelmente não muda nada, mas adiciona constexpr (o que significa que algumas funções definidas pelo usuário ainda podem ser boot estática) e thread variables ​​locais, o que abre uma nova lata de worms.

Prefácio: A palavra “estática” tem um grande número de diferentes significados em C ++. Não fique confuso.

Todos os seus objects têm duração de armazenamento estático . Isso é porque eles não são automáticos nem dynamics. (Nem thread-local, embora thread-local é um pouco como estático.)

Em C ++, os objects estáticos são inicializados em duas fases: boot estática e boot dinâmica.

  • A boot dinâmica requer que o código real seja executado, portanto, isso acontece para objects que iniciam com uma chamada de construtor ou em que o inicializador é uma expressão que só pode ser avaliada no tempo de execução.

  • A boot estática é quando o inicializador é conhecido estaticamente e nenhum construtor precisa ser executado. (Inicialização estática é boot -zero ou boot- constante .) Este é o caso de suas variables int com inicializador constante, e você tem a garantia de que elas são de fato inicializadas na fase estática.

  • (Variáveis ​​de armazenamento estático com boot dinâmica também são inicializadas com zero estaticamente antes que qualquer outra coisa aconteça.)

O ponto crucial é que a fase de boot estática não é “executada”. Os dados estão lá desde o início. Isso significa que não há “pedidos” ou qualquer outra propriedade dinâmica relacionada à boot estática. Os valores iniciais são codificados no seu programa binário, se você quiser.

Quando essas quatro variables ​​são inicializadas?

Como você diz, isso acontece antes da boot do programa, ou seja, antes do início da main . C não especifica mais; em C ++, isso ocorre durante a fase de boot estática antes de objects com construtores ou inicializadores mais complicados.

Onde valores para boot como 5 e 4 são armazenados durante a compilation?

Normalmente, os valores diferentes de zero são armazenados em um segmento de dados no arquivo de programa, enquanto os valores zero estão em um segmento bss que apenas reserva memory suficiente para as variables. Quando o programa é iniciado, o segmento de dados é carregado na memory e o segmento bss é definido como zero. (Claro, o padrão de linguagem não especifica isso, então um compilador poderia fazer outra coisa, como gerar código para inicializar cada variável antes de executar main ).

Parafraseado a partir do padrão:

Todas as variables ​​que não possuem duração de armazenamento dynamic, não possuem duração de armazenamento local de encadeamento e não são locais, possuem duração de armazenamento estático. Em outras palavras, todas as globais têm duração de armazenamento estático.

Objetos estáticos com boot dinâmica não são necessariamente criados antes da primeira instrução na function principal. É a implementação definida para determinar se esses objects são criados antes da primeira instrução no main, ou antes do primeiro uso de qualquer function ou variável definida na mesma unidade de tradução que a variável estática a ser inicializada.

Portanto, no seu código, global_int1 e static_int1 são definitivamente inicializados antes da primeira instrução no main, porque eles são inicializados estaticamente. No entanto, global_int2 e static_int2 são dinamicamente inicializados, portanto, sua boot é implementada de acordo com a regra que mencionei acima.

Quanto ao segundo ponto, não tenho certeza se entendi o que você quer dizer. Você poderia esclarecer?