A seção $ 3.6.1 / 1 do padrão C ++ lê:
Um programa deve conter uma função global chamada main , que é o início designado do programa.
Agora considere este código,
int square(int i) { return i*i; }
int user_main()
{
for ( int i = 0 ; i < 10 ; ++i )
std::cout << square(i) << endl;
return 0;
}
int main_ret= user_main();
int main()
{
return main_ret;
}
Este código de exemplo faz o que pretendo fazer, ou seja, imprimir o quadrado de números inteiros de 0 a 9, antes de entrar na main()
função que deveria ser o "início" do programa.
Também o compilei com a -pedantic
opção GCC 4.5.0. Não dá erro, nem aviso!
Então, minha pergunta é:
Esse código é realmente compatível com o padrão?
Se estiver em conformidade com o padrão, não invalida o que o Padrão diz? main()
não é o início deste programa! user_main()
executado antes do main()
.
Entendo que, para inicializar a variável global main_ret
, o use_main()
executa primeiro, mas isso é uma coisa completamente diferente; o ponto é que, isso não invalida a declaração citada $ 3.6.1 / 1 do Padrão, como main()
não é o início do programa; é na verdade a fim de este programa!
EDITAR:
Como você define a palavra 'start'?
Tudo se resume à definição da frase "início do programa" . Então, como exatamente você o define?
main()
como "início do programa"static
duração de armazenamento e, como tal, esses objetos pertencentes a diferentes unidades de conversão podem ser inicializados em qualquer ordem (porque a ordem não é especificada pelo padrão). Não tenho certeza se isso responde à sua pergunta, embora seja o que eu poderia dizer no contexto deste tópico.Você está lendo a frase incorretamente.
O padrão está DEFININDO a palavra "iniciar" para os fins do restante do padrão. Não diz que nenhum código é executado antes de
main
ser chamado. Diz que o início do programa é considerado como funçãomain
.Seu programa é compatível. Seu programa não "iniciou" até que o principal seja iniciado. O construtor é chamado antes que o programa "inicie" de acordo com a definição de "start" no padrão, mas isso dificilmente importa. Um monte de código é executado antes
main
é sempre chamado em cada programa, não apenas neste exemplo.Para fins de discussão, o código do construtor é executado antes do 'início' do programa e é totalmente compatível com o padrão.
fonte
Seu programa não será vinculado e, portanto, não será executado, a menos que haja um principal. No entanto, main () não causa o início da execução do programa, porque os objetos no nível do arquivo têm construtores que são executados anteriormente e seria possível escrever um programa inteiro que dura sua vida útil antes que main () seja atingido e permita que o próprio main tenha um corpo vazio.
Na realidade, para impor isso, você teria que ter um objeto construído antes do main e seu construtor para invocar todo o fluxo do programa.
Veja isso:
O fluxo do seu programa resultaria efetivamente de
Foo::Foo()
fonte
Você marcou a pergunta como "C" também; portanto, falando estritamente sobre C, sua inicialização falhará conforme a seção 6.7.8 "Inicialização" do padrão ISO C99.
O mais relevante nesse caso parece ser a restrição 4, que diz:
Portanto, a resposta para sua pergunta é que o código não é compatível com o padrão C.
Você provavelmente desejaria remover a tag "C" se estivesse interessado apenas no padrão C ++.
fonte
A Seção 3.6 como um todo é muito clara sobre a interação
main
e as inicializações dinâmicas. O "início designado do programa" não é usado em nenhum outro lugar e é apenas descritivo da intenção geral demain()
. Não faz sentido interpretar essa frase de maneira normativa que contradiga os requisitos mais detalhados e claros da Norma.fonte
O compilador geralmente precisa adicionar código antes de main () para ser compatível com o padrão. Porque o padrão especifica que a initalização de globais / estáticas deve ser feita antes que o programa seja executado. E, como mencionado, o mesmo vale para os construtores de objetos colocados no escopo do arquivo (globais).
Portanto, a pergunta original também é relevante para C, porque em um programa em C você ainda teria a inicialização global / estática antes de iniciar o programa.
Os padrões assumem que essas variáveis são inicializadas através de "magia", porque não dizem como devem ser definidas antes da inicialização do programa. Eu acho que eles consideraram isso algo fora do escopo de um padrão de linguagem de programação.
Editar: veja, por exemplo, ISO 9899: 1999 5.1.2:
A teoria por trás de como essa "mágica" deveria ser feita remonta ao nascimento de C, quando era uma linguagem de programação destinada a ser usada apenas no SO UNIX, em computadores baseados em RAM. Em teoria, o programa seria capaz de carregar todos os dados pré-inicializados do arquivo executável na RAM, ao mesmo tempo em que o próprio programa era carregado na RAM.
Desde então, os computadores e o SO evoluíram, e o C é usado em uma área muito maior do que o inicialmente previsto. Um sistema operacional moderno para PC possui endereços virtuais, etc., e todos os sistemas embarcados executam código da ROM, não da RAM. Portanto, existem muitas situações em que a RAM não pode ser configurada "automaticamente".
Além disso, o padrão é muito abstrato para saber algo sobre pilhas e memória de processo etc. Essas coisas também devem ser feitas antes do início do programa.
Portanto, praticamente todo programa C / C ++ possui algum código init / "copy-down" que é executado antes que o main seja chamado, a fim de estar em conformidade com as regras de inicialização dos padrões.
Como exemplo, os sistemas embarcados geralmente têm uma opção chamada "inicialização não compatível com ISO", em que toda a fase de inicialização é ignorada por motivos de desempenho e, em seguida, o código é iniciado diretamente do principal. Mas esses sistemas não estão em conformidade com os padrões, pois você não pode confiar nos valores init de variáveis globais / estáticas.
fonte
Seu "programa" simplesmente retorna um valor de uma variável global. Tudo o resto é código de inicialização. Portanto, o padrão é válido - você apenas tem um programa muito trivial e uma inicialização mais complexa.
fonte
main () é uma função do usuário chamada pela biblioteca de tempo de execução C.
consulte também: Evitando o principal (ponto de entrada) em um programa C
fonte
Parece uma semântica em inglês. O OP se refere ao seu bloco de código primeiro como "código" e depois como "programa". O usuário escreve o código e, em seguida, o compilador grava o programa.
fonte
main é chamado após a inicialização de todas as variáveis globais.
O que o padrão não especifica é a ordem de inicialização de todas as variáveis globais de todos os módulos e bibliotecas vinculadas estaticamente.
fonte
Sim, main é o "ponto de entrada" de todos os programas C ++, exceto as extensões específicas da implementação. Mesmo assim, algumas coisas acontecem antes da inicialização principal, principalmente a global, como para main_ret.
fonte