¿Puede la función principal llamarse a sí misma en C++?
¿Alguien puede decir cuál es el problema del siguiente código?
int main () {
return main();
}
Lo probé, se compila correctamente. Está funcionando para siempre. ¿Algún truco detrás de escena?
TLDR : las llamadas main
dan como resultado un comportamiento indefinido.
Parece haber confusión sobre la terminología utilizada en el estándar y las implicaciones que tiene para el programador y el compilador.
En primer lugar, el estándar por sí solo determina todo lo relacionado con el lenguaje C++. Si su versión particular de un compilador en particular permite alguna acción particular, eso no influye en si esa acción es legal o no. Para el resto de la publicación, me refiero al estándar ISO03.
Entonces, para citar una vez más, la norma dice en §3.6.1.3:
La función main no se utilizará dentro de un programa.
Además, el artículo 3.2 define "usado" como:
Se utiliza un objeto o función no sobrecargada si su nombre aparece en una expresión potencialmente evaluada.
Esto significa que una vez que el programa comienza a ejecutarse, no se main
debe volver a ingresar nunca más . Eso significa que los programadores no pueden llamar a main
, eso significa que el compilador no puede insertar otra llamada main
(por qué lo haría, quién sabe), no puedes tomar la dirección principal y llamarla, etc. Ni siquiera puedes tener el potencial de llamar a main
.
La única llamada main
debe ser mediante la biblioteca de tiempo de ejecución en la que se ejecuta el programa; todas las demás llamadas invocan un comportamiento indefinido. (¡Lo que significa que podría pasar cualquier cosa!)
Ahora sobre el comportamiento del compilador:
Una regla diagnosticable se define como (§1.4.1):
El conjunto de reglas diagnosticables consta de todas las reglas sintácticas y semánticas de esta Norma Internacional, excepto aquellas reglas que contienen una notación explícita de que "no se requiere diagnóstico" o que se describen como resultantes de un "comportamiento indefinido".
En nuestro caso, §3.6.1.3 define una regla diagnosticable. Esto es lo que deberían hacer los compiladores según §1.4.2:
— Si un programa no contiene violaciones de las reglas de esta Norma Internacional, una implementación conforme deberá, dentro de sus límites de recursos, aceptar y ejecutar correctamente3) ese programa.
— Si un programa contiene una violación de cualquier regla diagnosticable, una implementación conforme deberá emitir al menos un mensaje de diagnóstico, excepto que
— Si un programa contiene una violación de una regla para la cual no se requiere diagnóstico, esta Norma Internacional no impone ningún requisito a las implementaciones. con respecto a ese programa.
Por tanto, los compiladores no están obligados a hacer cumplir las reglas. Todo lo que los compiladores tienen que hacer es tomar programas bien formados (§1.3.14) y convertirlos en un programa ejecutable. Un compilador es libre de advertir, dar errores, etc. como quiera, siempre y cuando no entre en conflicto con el lenguaje. Se requiere mostrar un mensaje en nuestro caso particular, según la cláusula segunda.
Para este problema en particular, en gcc la -pedantic
opción advertirá sobre la ilegalidad de realizar llamadas main
dentro del programa. Visual Studio no advertirá sobre la llamada main
, pero en cualquier nivel de advertencia (mayor que 0) advertirá sobre la naturaleza recursiva del programa.
¿Qué significa todo esto en términos de las respuestas que debería esperar? Significa que no tiene ningún sentido intentar definir con certeza qué hará el fragmento de código publicado. Llamar da main
como resultado un comportamiento indefinido y tratar de definir un comportamiento indefinido es obviamente una causa perdida. La única respuesta honesta que alguien puede dar a "¿qué pasa cuando llamo main
?" es algo."
Espero que esto aclare las cosas.
Llamar main
a C++ es ilegal (§3.6.1.3):
La función main no se utilizará dentro de un programa.
Su compilador permite comportamientos ilegales.
Se repite para siempre porque, bueno, main
llama main
, quién llama main
, quién llama main
, etc.
Es como ser un traficante de drogas. Bastante ilegal, pero compila e incluso funciona bien durante algún tiempo...