En realidad, no es una diferencia, pero es sutil. Tiene más implicaciones para C ++, pero las diferencias son importantes.
Cuando llamo , se llamarán returna los main()destructores para mis objetos de ámbito local. Si llamo exit(), no se llamará a destructor para mis objetos localmente alcanzados. Vuelve a leer eso. exit() no vuelve . Eso significa que una vez que lo llamo, no hay "backsies". Los objetos que haya creado en esa función no serán destruidos. A menudo esto no tiene implicaciones, pero a veces lo hace, como cerrar archivos (¿seguramente desea que todos sus datos se vacíen en el disco?).
Tenga en cuenta que los staticobjetos se limpiarán incluso si llama exit(). Finalmente tenga en cuenta que si usa abort(), no se destruirán objetos. Es decir, no se llamarán a sus destructores objetos globales, objetos estáticos ni objetos locales.
Proceda con precaución al favorecer la salida sobre el retorno.
http://groups.google.com/group/gnu.gcc.help/msg/8348c50030cfd15a
thread_localque se llamará a los destructores de objetos. Los destructores de otros objetos locales todavía no se llaman. ideone.com/Y6Dh3fexit()cerrar los archivos limpiamente es realmente incorrecto. El único momento en que los datos podrían no vaciarse es en el caso opuesto: es decir, si uno usareturndesdemain()y ha llamadosetbuf()osetvbuf()con un búfer declarado como almacenamiento automático enmain()(como se discute en la respuesta de R. a continuación). Es realmente una lástima que esta pregunta esté etiquetada con C y C ++ (y con estilo de codificación, ¡no es un problema de estilo!).Otra diferencia:
exites una función de biblioteca estándar, por lo que debe incluir encabezados y enlaces con la biblioteca estándar. Para ilustrar (en C ++), este es un programa válido:pero para usar
exitnecesitarás incluir:Además, esto agrega una suposición adicional: que llamar
exitdesdemaintiene los mismos efectos secundarios que devolver cero. Como otros han señalado, esto depende de qué tipo de ejecutable esté construyendo (es decir, quién llamamain). ¿Estás codificando una aplicación que usa el tiempo de ejecución C? ¿Un complemento maya? ¿Un servicio de Windows? ¿Un conductor? Cada caso requerirá investigación para ver siexites equivalente areturn. En mi humilde opinión, usarexitcuando realmente te refieresreturnsolo hace que el código sea más confuso. OTOH, si realmente quieres decirexit, entonces utilízalo .fuente
Hay al menos una razón para preferir
exit: si alguno de susatexitcontroladores se refiere a datos de duración de almacenamiento automáticomain, o si usósetvbufosetbufasignó a una de las transmisiones estándar un búfer de duración de almacenamiento automáticomain, luego regresa demainproduce comportamiento indefinido, pero la llamadaexites válida.Sin embargo, otro uso potencial (generalmente reservado para programas de juguetes) es salir de un programa con invocaciones recursivas de
main.fuente
main(): es solo una función como cualquier otra. Por otro lado, dado que tiene una mención especial en el estándar, el estándar debe ser bastante cuidadoso acerca de cómo se definemain()y las cosas cercanas y queridas. Sin embargo, al final, el estándar no requiere (y no debe ) que los compiladores hagan algo especial sobre el almacenamiento automáticomain(). Lea atentamente la Nota al pie # 11 debajo del párrafo al que hizo referencia en su comentario.Siempre uso
returnporque el prototipo estándar paramain()dice que devuelve unint.Dicho esto, algunas versiones de los estándares dan
mainun tratamiento especial y suponen que devuelve 0 si no hay unareturndeclaración explícita . Dado el siguiente código:G ++ solo genera una advertencia
foo()e ignora el retorno faltante demain:fuente
returnpara finalizar su ejecución. Llamarexit()también es una forma válida, y a veces necesaria, de finalizar la ejecución de cualquier función. De hecho, como yo y otros hemos descrito en otra parte, llamarexit()incluso desdemain()transmite una intención mucho más clara de salir de todo el proceso, preserva el almacenamiento automático hasta la salida del proceso y facilita el mantenimiento durante la futura refactorización del código. Para C usarreturninmain()cuando la intención es terminar el proceso es, por lo tanto, una mala práctica.I ENÉRGICAMENTE segundo el comentario de R. acerca del uso de la salida () con el fin de evitar tener almacenamiento automático en
main()recuperada antes de que el programa realmente extremos. Unareturn X;declaración enmain()no es exactamente equivalente a una llamada aexit(X);, ya que el almacenamiento dinámico demain()desaparece cuandomain()regresa, pero no desaparece si se realiza una llamada aexit().Además, en C o en cualquier lenguaje similar a C, una
returndeclaración sugiere al lector que la ejecución continuará en la función de llamada, y si bien esta continuación de la ejecución suele ser técnicamente cierta si cuenta la rutina de inicio de C que llamó a sumain()función, no es exactamente lo que quieres decir cuando quieres terminar el proceso.Después de todo, si usted desea terminar su programa desde cualquier otra función, excepto
main()que debe llamarexit(). Hacerlo de manera consistentemain()también hace que su código sea mucho más legible, y también hace que sea mucho más fácil para cualquiera volver a factorizar su código; es decir, el código copiado demain()alguna otra función no se comportará mal debido areturndeclaraciones accidentales que deberían haber sidoexit()llamadas.Entonces, combinando todos estos puntos, la conclusión es que es un mal hábito , al menos para C, usar una
returndeclaración para finalizar el programamain().fuente
exit()en general, pero lo uso si unathrowo otrasabort()alternativas no funcionan en un contexto específico. Pero especialmente eviteexit()en main, y use return en main en su lugar como práctica típica.Con algunos compiladores para plataformas poco comunes,
exit()podría traducir su argumento al valor de salida de su programa, mientras que un retorno demain()podría simplemente pasar el valor directamente al entorno host sin ninguna traducción.El estándar requiere un comportamiento idéntico en estos casos (específicamente, dice que devolver algo que sea
intcompatiblemain()debería ser equivalente a llamarexit()con ese valor). El problema es que diferentes sistemas operativos tienen diferentes convenciones para interpretar los valores de salida. En muchos sistemas (¡MUCHOS!), 0 significa éxito y cualquier otra cosa es un fracaso. Pero en, por ejemplo, VMS, los valores impares significan éxito y los pares significan fracaso. Si devolvió 0 desdemain(), un usuario de VMS vería un mensaje desagradable sobre una infracción de acceso. En realidad no hubo una infracción de acceso, ese fue simplemente el mensaje estándar asociado con el código de falla 0.Luego, ANSI apareció y fue bendecido
EXIT_SUCCESSyEXIT_FAILUREcomo argumentos a los que podrías pasarexit(). La norma también dice queexit(0)debe comportarse de forma idéntica aexit(EXIT_SUCCESS), por lo que la mayoría de las implementaciones definenEXIT_SUCCESSa0.El estándar, por lo tanto, lo pone en un enlace en VMS, ya que no deja una forma estándar de devolver un código de falla que tiene el valor 0.
El compilador VAX / VMS C de principios de la década de 1990, por lo tanto, no interpretó el valor de retorno
main(), simplemente devolvió cualquier valor al entorno host. Pero si lo usaraexit(), haría lo que el estándar requería: traducirEXIT_SUCCESS(o0) en un código de éxito yEXIT_FAILUREen un código de falla genérico. Para usarloEXIT_SUCCESS, tenía que pasárseloexit(), no podía devolverlomain(). No sé si las versiones más modernas de ese compilador conservaron ese comportamiento.Un programa C portátil solía verse así:
Aparte: si recuerdo correctamente, la convención VMS para valores de salida tiene más matices que impar / par. En realidad, usa algo como los tres bits bajos para codificar un nivel de gravedad. En términos generales, sin embargo, los niveles de gravedad impares indicaron éxito o información variada y los pares indicaron errores.
fuente
returnedde maneramaindiferente del valor pasado aexit, pero el estándar dice específicamente: "Si el tipo de retorno de lamainfunción es un tipo compatible conint, un retorno de la llamada inicial a lamainfunción es equivalente a llamar a laexitfunción con el valor devuelto por lamainfunción como argumento ". Eso es C11; C89 / C90 tenía casi la misma redacción.EXIT_SUCCESS, no había forma de devolver un estado de falla específico de la plataforma con el valor 0, por lo que algunos de los compiladores de la era trataron el retorno desde el principal Yexit()diferente.En C regresar de
maines exactamente lo mismo que llamarexitcon el mismo valor.La sección 5.1.2.2.3 de los estados estándar de C :
Las reglas para C ++ son un poco diferentes como se menciona en otras respuestas.
fuente
En realidad, existe una diferencia entre
exit(0)yreturn(0)enmain- cuando sumainfunción se llama varias veces.El siguiente programa
Correr como
Resultará en la siguiente salida:
Sin embargo este:
No imprimirá nada independientemente de los argumentos.
Si está seguro de que nadie lo llamará
mainexplícitamente, técnicamente no es una gran diferencia en general, pero mantener un código más claroexitse vería mucho mejor. Si por alguna razón desea llamarmain, debe ajustarlo a sus necesidades.Hablando de C.
fuente