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

La sección $ 3.6.1 / 1 de las lecturas estándar de C ++,

Un progtwig debe contener una función global llamada main , que es el inicio designado del progtwig.

Ahora considera 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 muestra hace lo que pretendo que haga, es decir, imprimir el cuadrado de enteros de 0 a 9, antes de ingresar a la función main() que se supone que es el “inicio” del progtwig.

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

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

Entonces mi pregunta es

¿Es este código realmente conforme?

Si cumple con los estándares, ¿no invalida lo que dice el Estándar? main() no es inicio de este progtwig! user_main() ejecutado antes de main() .

Entiendo que para inicializar la variable global main_ret , use_main() ejecuta primero, pero eso es completamente diferente; el punto es que invalida el enunciado citado $ 3.6.1 / 1 del Estándar, ya que main() NO es el inicio del progtwig; de hecho, es el final de este progtwig!


EDITAR:

¿Cómo defines la palabra ‘comenzar’?

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

No, C ++ hace muchas cosas para “configurar el ambiente” antes de la llamada de main; sin embargo, main es el inicio oficial de la parte “especificada por el usuario” del progtwig 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 se puede controlar como bloques globales estáticos (para inicializar variables globales estáticas). Tenga en cuenta que, dado que no tiene plena control anterior a main, no tiene control total sobre el orden en que se inicializan los bloques estáticos.

Después de main, su código es conceptualmente “totalmente en control” del progtwig, en el sentido de que ambos pueden especificar las instrucciones que se ejecutarán y el orden en el que se realizarán. Multi-threading puede reordenar el orden de ejecución del código; pero, usted todavía tiene el control con C ++ porque ha especificado que las secciones de código se ejecuten (posiblemente) fuera de orden.

Estás leyendo la oración incorrectamente.

Un progtwig debe contener una función global llamada main, que es el inicio designado del progtwig.

El estándar es DEFINIENDO la palabra “inicio” para los propósitos del rest de la norma. No dice que no se ejecuta código antes de llamar a main . Dice que el inicio del progtwig se considera que está en la función main .

Tu progtwig cumple. Su progtwig no ha “comenzado” hasta que se haya iniciado main. El constructor se llama antes de que su progtwig “comience” de acuerdo con la definición de “inicio” en el estándar, pero eso no importa. Se ejecuta MUCHO código antes de llamar a main en cada progtwig, no solo este ejemplo.

Para los fines de discusión, su código de constructor se ejecuta antes del ‘inicio’ del progtwig, y ​​es totalmente compatible con el estándar.

Su progtwig no se vinculará 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 progtwig porque los objetos a nivel de archivo tienen constructores que se ejecutan de antemano y sería posible escribir un progtwig completo que ejecute su tiempo de vida antes de llegar a main () y dejar que main tenga un cuerpo vacío.

En realidad para hacer cumplir esto, tendrías que tener un objeto que se construye antes de main y su constructor para invocar todo el flujo del progtwig.

Mira este:

 class Foo { public: Foo(); // other stuff }; Foo foo; int main() { } 

El flujo de su progtwig provendría efectivamente de Foo::Foo()

También etiquetó la pregunta como “C”, y luego, 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.

Lo 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ática serán expresiones constantes o literales de cadena.

Entonces, la respuesta a su pregunta es que el código no cumple con el estándar C.

Probablemente desee eliminar la etiqueta “C” si solo estuviera interesado en el estándar C ++.

La sección 3.6 como un todo es muy clara acerca de la interacción de las inicializaciones main y dinámicas. El “inicio designado del progtwig” no se usa en ningún otro lado y es solo descriptivo de la intención general de main() . No tiene sentido interpretar esa frase de una manera normativa que contradice los requisitos más detallados y claros del Estándar.

El comstackdor a menudo tiene que agregar código antes de que main () sea estándar. Porque la norma especifica que la inicialización de globales / estáticas debe hacerse antes de que se ejecute el progtwig. Y como se mencionó, lo mismo vale para los constructores de objetos ubicados en el scope del archivo (globales).

Por lo tanto, la pregunta original también es relevante para C, porque en un progtwig C aún tendría que realizar la inicialización global o estática antes de poder iniciar el progtwig.

Los estándares asumen que estas variables se inicializan a través de “magia”, porque no dicen cómo se deben establecer antes de la inicialización del progtwig. Creo que consideraron eso como algo fuera del scope de un estándar de lenguaje de progtwigción.

Editar: Ver por ejemplo ISO 9899: 1999 5.1.2:

Todos los objetos con duración de almacenamiento estática deberán inicializarse (establecerse en sus valores iniciales) antes del inicio del progtwig. La manera y el momento de tal inicialización no están especificados.

La teoría detrás de cómo se debía hacer esta “magia” se remonta al nacimiento de C, cuando era un lenguaje de progtwigción destinado a ser utilizado solo para el sistema operativo UNIX, en computadoras basadas en RAM. En teoría, el progtwig podría cargar todos los datos preinicializados del archivo ejecutable en la RAM, al mismo tiempo que el progtwig se cargó en la RAM.

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

Además, el estándar es demasiado abstracto para saber algo acerca de las stacks y la memoria de proceso, etc. Estas cosas deben hacerse también antes de iniciar el progtwig.

Por lo tanto, casi todos los progtwigs C / C ++ tienen algún código init / “copy-down” que se ejecuta antes de llamar a main, a fin de cumplir con las reglas de inicialización de los estándares.

Como ejemplo, los sistemas integrados suelen tener una opción llamada “inicio no compatible con ISO” donde toda la fase de inicialización se omite por razones de rendimiento, y luego el código en realidad comienza directamente desde la principal. Pero tales sistemas no se ajustan a los estándares, ya que no puede confiar en los valores init de variables globales / estáticas.

Su “progtwig” 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 progtwig muy trivial y una inicialización más compleja.

main () es una función de usuario llamada por la biblioteca C runtime.

ver también: evitar el principal (punto de entrada) en un progtwig C

Parece una cuestión de semántica en inglés. El OP se refiere a su bloque de código primero como “código” y más tarde como el “progtwig”. El usuario escribe el código y luego el comstackdor escribe el progtwig.

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 vinculadas estáticamente.

Sí, main es el “punto de entrada” de cada progtwig C ++, exceptuando las extensiones específicas de la implementación. Aun así, algunas cosas suceden antes de la inicialización principal, especialmente global, como para main_ret.