A partir del estándar C99, se requiere que el compilador genere el equivalente a un return 0 o return EXIT_SUCCESS si no se proporciona ningún retorno al final de main . También hubo un cambio correspondiente e idéntico al estándar del lenguaje C++ en esa misma época. Estoy interesado en las razones de ambos y supuse que era poco probable que fueran cambios completamente separados y no relacionados.
Mi pregunta es:
¿Cuál fue la justificación documentada de este cambio?
Una respuesta ideal citaría fuentes autorizadas tanto para C como para C++, por lo que he etiquetado la pregunta con ambos idiomas.
Tenga en cuenta que, a diferencia de la pregunta ¿Cuáles son las razones a favor o en contra de devolver 0 desde main en ISO C++? , no estoy pidiendo consejo sobre si escribir return 0 en mis programas, estoy preguntando por qué se cambiaron los estándares del idioma.
Para ayudar a comprender el propósito de la pregunta, aquí hay un poco más del contexto:
Estudié los estándares buscando la respuesta yo mismo antes de preguntar aquí, pero no encontré la respuesta. Me pidieron que ayudara a escribir estándares de codificación para ambos idiomas para un grupo de programadores y quería asegurarme de que entendía por qué existe esta función para poder explicar con precisión su uso a otros.
En la sección 5.1.2.2.3 Finalización del programa de The New C Standard , el autor Derek Jones comenta sobre estas líneas del estándar C99:
alcanzar el } que termina la función principal devuelve un valor de 0
es:
La norma finalmente tiene que ceder ante las descuidadas prácticas existentes.
Lo que indica que la razón era abordar las malas prácticas de programación con respecto a devolver explícitamente un valor de main . Antes de esto, el estado devuelto era indefinido.
Indica que muchas implementaciones ya implementaron esto incluso en C90, por lo que el hecho de que este cambio ya reflejara una implementación común probablemente también ayudó.
El documento de justificación oficial para C99 apenas aborda esto. Parece que exit(0) se convirtió en el valor predeterminado para controlar el flujo al final de main porque exit(0) recibió una semántica portátil significativa.
Aquí están las dos secciones relevantes:
5.1.2.2.1 Inicio del programa
El comportamiento de los argumentos de
mainy de la interacción deexit,mainyatexit(ver §7.20.4.2) ha sido codificado para frenar cierta variedad no deseada en la representación de cadenasargvy en el significado de los valores devueltos pormain.La especificación de
argcyargvcomo argumentos para main reconoce una amplia práctica anterior.Se requiere que
argv[argc]sea un puntero nulo para proporcionar una verificación redundante para el final de la lista, también sobre la base de la práctica común.
maines la única función que puede ser declarada portablemente con cero o dos argumentos. (El número de argumentos de otras funciones debe coincidir exactamente entre la invocación y la definición). Este caso especial simplemente reconoce la práctica generalizada de dejar los argumentos enmaincuando el programa no accede a las cadenas de argumentos del programa. Si bien muchas implementaciones admiten más de dos argumentos paramain, dicha práctica no está bendecida ni prohibida por el Estándar; un programa que define main con tres argumentos no es estrictamente conforme (ver §J.5.1.).El estándar no exige la redirección de E/S de la línea de comandos, ya que se consideró que era una característica del sistema operativo subyacente en lugar del lenguaje C.
y
7.20.4.3 La función de salida
El argumento para
exites una indicación de estado devuelta al entorno invocador. En el sistema operativo UNIX, un valor de cero es el código de retorno correcto de un programa. A medida que el uso de C se ha extendido más allá de UNIX,exit(0)a menudo se ha conservado como un modismo que indica una terminación exitosa , incluso en sistemas operativos con diferentes sistemas de códigos de retorno. Por lo tanto, este uso se reconoce como estándar. Nunca ha habido una forma portátil de indicar una terminación fallida, ya que los argumentos paraexitestán definidos por la implementación. La macroEXIT_FAILUREse agregó a C89 para proporcionar dicha capacidad. También se agregóEXIT_SUCCESS.Además de las llamadas codificadas explícitamente por un programador, la
exitse invoca al regresar demain. Así, al menos en este caso, el organismo deexitno puede suponer la existencia de ningún objeto con duración de almacenamiento automático excepto los declarados enexit.El Comité consideró la adición de
_exit, pero la rechazó debido a preocupaciones de incompatibilidad con la especificación POSIX en la que se basa. Por ejemplo, una preocupación expresada es que_exitse especificó como una forma de salir de un controlador de señal sin activar otra señal, pero esa no es realmente la forma en que_exitse comporta en entornos POSIX. El Comité no deseaba dar a los programadores este tipo de falsas esperanzas. (Pero vea §7.20.4.4 para C99).