¿Puede la función principal llamarse a sí misma en C++?

Resuelto skydoor asked hace 14 años • 9 respuestas

¿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?

skydoor avatar Jan 25 '10 02:01 skydoor
Aceptado

TLDR : las llamadas maindan 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 maindebe 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 maindebe 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 -pedanticopción advertirá sobre la ilegalidad de realizar llamadas maindentro 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 maincomo 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.

GManNickG avatar Jan 24 '2010 20:01 GManNickG

Llamar maina 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, mainllama main, quién llama main, quién llama main, etc.

GManNickG avatar Jan 24 '2010 19:01 GManNickG

Es como ser un traficante de drogas. Bastante ilegal, pero compila e incluso funciona bien durante algún tiempo...

alemjerus avatar Jan 24 '2010 19:01 alemjerus