¿Es main () realmente el inicio de un programa C++?


La sección 3 3.6.1 / 1 del estándar C++ dice,

Un programa contendrá una función llamada main , que es la designado inicio del programa.

Ahora 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 ejemplo hace lo que pretendo hacer, es decir, imprimir el cuadrado de enteros de 0 a 9, antes de entrar en la función main() que se supone que es el "inicio" del programa.

Echa un vistazo a la salida aquí: http://www.ideone.com/Niy0R

También lo compilé con la opción -pedantic, GCC 4.5.0. No da ningún error, ni siquiera advertencia!

Así que mi pregunta es,

¿Este código es realmente conforme al estándar?

Si es conforme al estándar, entonces ¿no invalida lo que dice el Estándar? main() no es el inicio de este programa! user_main() ejecutado antes del main().

Entiendo que para inicializar la variable global main_ret, la use_main() se ejecuta primero, pero eso es algo completamente diferente; el punto es que invalida la declaración citada 3 3.6.1 / 1 del Estándar, ya que main() NO es el inicio del programa; es de hecho el fin de este programa!


EDITAR:

¿Cómo se define la palabra 'start'?

Se reduce a la definición de la frase "inicio del programa". Entonces, ¿cómo exactamente lo defines?

Author: Nawaz, 2011-01-24

11 answers

No, C++ hace muchas cosas para "establecer el entorno" antes de la llamada a main; sin embargo, main es el inicio oficial de la parte "especificada por el usuario" del programa C++.

Parte de la configuración del entorno no es controlable (como el código inicial para configurar std::cout; sin embargo, parte del entorno es controlable como bloques globales estáticos (para inicializar variables globales estáticas). Tenga en cuenta que como no tiene control total antes de main, no tiene control total sobre el pedido en el que los bloques estáticos se inicializan.

Después de main, su código está conceptualmente "totalmente en control" del programa, en el sentido de que puede especificar las instrucciones a realizar y el orden en el que realizarlas. Multi-threading puede reorganizar el orden de ejecución del código; pero, todavía está en control con C++ porque especificó que las secciones de código se ejecuten (posiblemente) fuera de orden.

 78
Author: Edwin Buck,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-01-24 16:11:30

Estás leyendo la oración incorrectamente.

Un programa contendrá una función global llamada main, que es el inicio designado del programa.

El estándar está DEFINIENDO la palabra "start" para los propósitos del resto del estándar. No dice que ningún código se ejecute antes de que se llame a main. Dice que el inicio del programa se considera que está en la función main.

Su programa es compatible. Su programa no ha "iniciado" hasta que se inicia main. El constructor se llama antes de que su programa "comience "de acuerdo con la definición de" inicio " en el estándar, pero eso apenas importa. Se ejecuta MUCHO código antes de que main se llame en cada programa, no solo en este ejemplo.

Para los propósitos de discusión, su código constructor se ejecuta antes del 'inicio' del programa, y eso es totalmente compatible con el estándar.

 84
Author: Adam Davis,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-01-24 16:26:55

Su programa no se enlazará y por lo tanto no se ejecutará a menos que haya un main. Sin embargo main() no causa el inicio de la ejecución del programa porque los objetos a nivel de archivo tienen constructores que se ejecutan de antemano y sería posible escribir un programa completo que ejecuta su vida útil antes de que main() se alcance y dejar que main tenga un cuerpo vacío.

En realidad para hacer cumplir esto tendría que tener un objeto que se construye antes de main y su constructor para invocar todos los flujo del programa.

, Mira esto:

class Foo
{
public:
   Foo();

 // other stuff
};

Foo foo;

int main()
{
}

El flujo de su programa se derivaría efectivamente de Foo::Foo()

 23
Author: CashCow,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-01-24 14:58:58

También etiquetó la pregunta como "C", entonces, hablando estrictamente sobre C, su inicialización debería fallar según la sección 6.7.8 "Inicialización" del estándar ISO C99.

La más relevante en este caso parece ser la restricción # 4 que dice:

Todas las expresiones en un inicializador para un objeto que tiene una duración de almacenamiento estático será expresiones constantes o literales de cadena.

Por lo tanto, la respuesta a su pregunta es que el código no es compatible con la C estándar.

Probablemente quiera eliminar la etiqueta "C" si solo estuviera interesado en el estándar C++.

 15
Author: Remo.D,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-01-24 21:56:45

La sección 3.6 en su conjunto es muy clara sobre la interacción de main y las inicializaciones dinámicas. El "inicio designado del programa" no se usa en ningún otro lugar y es solo descriptivo de la intención general de main(). No tiene sentido interpretar esa frase de una manera normativa que contradiga los requisitos más detallados y claros de la Norma.

 10
Author: aschepler,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-01-24 15:37:42

El compilador a menudo tiene que agregar código antes de main() para que sea compatible con el estándar. Porque el estándar especifica que la inicialización de globals/statics debe hacerse antes de que se ejecute el programa. Y como se mencionó, lo mismo ocurre con los constructores de objetos colocados en el ámbito de archivo (globals).

Por lo tanto, la pregunta original es relevante para C también, porque en un programa C todavía tendría que hacer la inicialización globals/static antes de que el programa pueda ser comenzar.

Los estándares asumen que estas variables se inicializan a través de "magia", porque no dicen cómo deben establecerse antes de la inicialización del programa. Creo que lo consideraron como algo fuera del alcance de un estándar de lenguaje de programación.

Editar: Ver por ejemplo ISO 9899:1999 5.1.2:

Todos los objetos con almacenamiento estático duración se inicializará (establecido en sus valores iniciales) antes del programa Inicio. La manera y el momento de tales inicialización son de lo contrario indeterminado.

La teoría detrás de cómo se iba a hacer esta "magia" se remonta al nacimiento de C, cuando era un lenguaje de programación destinado a ser utilizado solo para el sistema operativo UNIX, en computadoras basadas en RAM. En teoría, el programa sería capaz de cargar todos los datos preinicializados desde el archivo ejecutable en la RAM, al mismo tiempo que el programa en sí fue cargado a la RAM.

Desde entonces, las computadoras y el sistema operativo han evolucionado, y C se usa de una manera mucho más amplia área de lo previsto originalmente. Un sistema operativo de PC moderno tiene direcciones virtuales, etc., y todos los sistemas embebidos ejecutan código desde ROM, no desde RAM. Por lo tanto, hay muchas situaciones en las que la RAM no se puede configurar "automáticamente".

Además, el estándar es demasiado abstracto para saber nada sobre pilas y memoria de proceso, etc. Estas cosas deben hacerse también, antes de que se inicie el programa.

Por lo tanto, casi todos los programas C / C++ tienen algún código init/"copy-down" que se ejecuta antes de que se llame a main, en para cumplir con las reglas de inicialización de las normas.

Como ejemplo, los sistemas embebidos típicamente tienen una opción llamada "arranque no compatible con ISO" donde toda la fase de inicialización se omite por razones de rendimiento, y luego el código comienza directamente desde main. Pero tales sistemas no se ajustan a los estándares, ya que no se puede confiar en los valores de inicio de las variables globales/estáticas.

 9
Author: Lundin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-01-24 15:47:08

Su "programa" simplemente devuelve un valor de una variable global. Todo lo demás es código de inicialización. Por lo tanto, el estándar se mantiene: solo tiene un programa muy trivial y una inicialización más compleja.

 4
Author: Zac Howland,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-01-24 15:14:47

Main() es una función de usuario llamada por la biblioteca de tiempo de ejecución de C.

Ver también: Evitar el principal (punto de entrada) en un programa C

 4
Author: sylvanaar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 11:54:28

Parece una discusión semántica inglesa. El OP se refiere a su bloque de código primero como " código "y más tarde como el "programa"."El usuario escribe el código, y luego el compilador escribe el programa.

 2
Author: dSerk,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-06-27 01:31:22

Main se llama después de inicializar todas las variables globales.

Lo que el estándar no especifica es el orden de inicialización de todas las variables globales de todos los módulos y bibliotecas enlazadas estáticamente.

 1
Author: vz0,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-01-24 22:36:37

Sí, main es el "punto de entrada" de cada programa de C++, excepto las extensiones específicas de la implementación. Aun así, algunas cosas suceden antes de main, notablemente la inicialización global como para main_ret.

 0
Author: Fred Nurk,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-01-24 15:01:12