Estándar C - Entorno alojado
Para un entorno alojado (ese es el normal), el estándar C11 (ISO / IEC 9899: 2011) dice:
5.1.2.2.1 Inicio del programa
Se nombra la función llamada al inicio del programa main
. La implementación no declara ningún prototipo para esta función. Se definirá con un tipo de retorno de int
y sin parámetros:
int main(void) { /* ... */ }
o con dos parámetros (referidos aquí como argc
y argv
, aunque se pueden usar nombres, ya que son locales para la función en la que se declaran):
int main(int argc, char *argv[]) { /* ... */ }
o equivalente; 10) o de alguna otra manera definida por la implementación.
Si se declaran, los parámetros de la función principal obedecerán las siguientes restricciones:
- El valor de
argc
será no negativo.
argv[argc]
será un puntero nulo.
- Si el valor de
argc
es mayor que cero, los miembros de la matriz a argv[0]
través de
argv[argc-1]
inclusivo contendrán punteros a las cadenas, a los que el entorno host les da valores definidos por la implementación antes del inicio del programa. La intención es proporcionar al programa información determinada antes del inicio del programa desde cualquier otra parte del entorno alojado. Si el entorno host no es capaz de suministrar cadenas con letras en mayúsculas y minúsculas, la implementación garantizará que las cadenas se reciban en minúsculas.
- Si el valor de
argc
es mayor que cero, la cadena a la que apunta argv[0]
representa el nombre del programa; argv[0][0]
será el carácter nulo si el nombre del programa no está disponible en el entorno del host. Si el valor de argc
es mayor que uno, las cadenas señaladas por argv[1]
mediante argv[argc-1]
representan los parámetros del programa.
- Los parámetros
argc
y argv
las cadenas a las que apunta la argv
matriz serán modificables por el programa y conservarán sus últimos valores almacenados entre el inicio y la finalización del programa.
10) Por lo tanto, int
se puede reemplazar por un nombre typedef definido como int
, o el tipo de argv
se puede escribir como
char **argv
, y así sucesivamente.
Terminación del programa en C99 o C11
El valor devuelto desde main()
se transmite al 'entorno' de una manera definida por la implementación.
5.1.2.2.3 Terminación del programa
1 Si el tipo de retorno de la main
función es un tipo compatible con int
, un retorno de la llamada inicial a la main
función es equivalente a llamar a la exit
función con el valor devuelto por la main
función como argumento; 11) alcanzar el }
que finaliza la
main
función devuelve un valor de 0. Si el tipo de retorno no es compatible int
, el estado de terminación devuelto al entorno host no está especificado.
11) De conformidad con 6.2.4, la vida útil de los objetos con una duración de almacenamiento automática declarada main
habrá finalizado en el primer caso, incluso cuando no lo hubieran hecho en el segundo.
Tenga en cuenta que 0
es obligatorio como 'éxito'. Puede usar EXIT_FAILURE
y EXIT_SUCCESS
desde <stdlib.h>
si lo prefiere, pero 0 está bien establecido, y también lo es 1. Vea también Códigos de salida mayores que 255 - ¿posible? .
En C89 (y, por lo tanto, en Microsoft C), no hay una declaración sobre lo que sucede si la main()
función regresa pero no especifica un valor de retorno; Por lo tanto, conduce a un comportamiento indefinido.
7.22.4.4 La exit
función
¶5 Finalmente, el control se devuelve al entorno del host. Si el valor de status
es cero o EXIT_SUCCESS
, se devuelve una forma definida por la implementación del estado de terminación exitosa . Si el valor de status
es EXIT_FAILURE
, se devuelve una forma definida por la implementación del estado de terminación fallida . De lo contrario, el estado devuelto está definido por la implementación.
Standard C ++ - Entorno Hospedado
El estándar C ++ 11 (ISO / IEC 14882: 2011) dice:
3.6.1 Función principal [basic.start.main]
¶1 Un programa contendrá una función global llamada main, que es el inicio designado del programa. [...]
¶2 Una implementación no predefinirá la función principal. Esta función no se sobrecargará. Tendrá un tipo de retorno de tipo int, pero de lo contrario su tipo está definido por la implementación. Todas las implementaciones deberán permitir las dos definiciones siguientes de main:
int main() { /* ... */ }
y
int main(int argc, char* argv[]) { /* ... */ }
En la última forma se argc
indicará el número de argumentos pasados al programa desde el entorno en el que se ejecuta el programa. Si argc
no es cero, estos argumentos se proporcionarán argv[0]
mediante argv[argc-1]
punteros a los caracteres iniciales de las cadenas multibyte terminadas en nulo (NTMBS) (17.5.2.1.4.2) y argv[0]
serán el puntero al carácter inicial de un NTMBS que representa el nombre utilizado para invocar el programa o ""
. El valor de argc
no será negativo. El valor de argv[argc]
será 0. [Nota: Se recomienda agregar más parámetros (opcionales) después argv
. —Nota final]
¶3 La función main
no se utilizará dentro de un programa. El enlace (3.5) de main
está definido por la implementación. [...]
¶5 Una declaración de retorno en main tiene el efecto de abandonar la función main (destruir cualquier objeto con duración de almacenamiento automática) y llamar std::exit
con el valor return como argumento. Si el control llega al final de main sin encontrar una declaración de retorno, el efecto es el de ejecutar
return 0;
El estándar C ++ dice explícitamente "[la función principal] tendrá un tipo de tipo de retorno int
, pero de lo contrario su tipo está definido por la implementación", y requiere las mismas dos firmas que el estándar C para ser admitido como opciones. Por lo tanto, el estándar C ++ no permite directamente un 'void main ()', aunque no hay nada que pueda hacer para detener una implementación no estándar que permita alternativas. Tenga en cuenta que C ++ prohíbe que el usuario llame main
(pero el estándar C no).
Hay un párrafo de §18.5 Inicio y terminación en el estándar C ++ 11 que es idéntico al párrafo de §7.22.4.4 La exit
función en el estándar C11 (citado anteriormente), aparte de una nota al pie (que simplemente documenta queEXIT_SUCCESS
y EXIT_FAILURE
está definido en <cstdlib>
).
Estándar C - Extensión común
Clásicamente, los sistemas Unix admiten una tercera variante:
int main(int argc, char **argv, char **envp) { ... }
El tercer argumento es una lista de punteros a cadenas con terminación nula, cada una de las cuales es una variable de entorno que tiene un nombre, un signo de igual y un valor (posiblemente vacío). Si no usa esto, aún puede acceder al medio ambiente a través de ' extern char **environ;
'. Esta variable global es única entre aquellos en POSIX en que no tiene un encabezado que la declare.
El estándar C reconoce esto como una extensión común, documentada en el Anexo J:
J.5.1 Argumentos del entorno
¶1 En un entorno alojado, la función principal recibe un tercer argumento, char *envp[]
que apunta a una matriz de punteros terminados en nulo char
, cada uno de los cuales apunta a una cadena que proporciona información sobre el entorno para esta ejecución del programa (5.1. 2.2.1).
Microsoft C
El compilador de Microsoft VS 2010 es interesante. El sitio web dice:
La sintaxis de declaración para main es
int main();
u opcionalmente
int main(int argc, char *argv[], char *envp[]);
Alternativamente, las funciones main
y wmain
se pueden declarar como de retorno void
(sin valor de retorno). Si declara main
o wmain
como devolución nula, no puede devolver un código de salida al proceso principal o al sistema operativo utilizando una declaración de devolución. Para devolver un código de salida cuando main
o wmain
se declara como void
, debe usar la exit
función
No me queda claro qué sucede (qué código de salida se devuelve al padre o al SO) cuando un programa con void main()
sale, y el sitio web de MS también permanece en silencio.
Curiosamente, MS no prescribe la versión de dos argumentos main()
que requieren los estándares C y C ++. Solo prescribe una forma de tres argumentos donde el tercer argumento eschar **envp
, un puntero a una lista de variables de entorno.
La página de Microsoft también enumera algunas otras alternativas: wmain()
que requieren cadenas de caracteres anchas y algunas más.
La versión de Microsoft Visual Studio 2005 de esta página no aparece void main()
como alternativa. Las versiones de Microsoft Visual Studio 2008 en adelante sí.
Estándar C - Entorno independiente
Como se señaló anteriormente, los requisitos anteriores se aplican a los entornos alojados. Si está trabajando con un entorno independiente (que es la alternativa a un entorno alojado), entonces el estándar tiene mucho menos que decir. Para un entorno independiente, la función llamada al inicio del programa no necesita ser llamada main
y no hay restricciones en su tipo de retorno. El estándar dice:
5.1.2 Entornos de ejecución
Se definen dos entornos de ejecución: independiente y alojado. En ambos casos, el inicio del programa ocurre cuando el entorno de ejecución invoca una función C designada. Todos los objetos con una duración de almacenamiento estático se inicializarán (se establecerán en sus valores iniciales) antes del inicio del programa. La manera y el momento de dicha inicialización no están especificados. La finalización del programa devuelve el control al entorno de ejecución.
5.1.2.1 Entorno independiente
En un entorno independiente (en el que la ejecución del programa C puede tener lugar sin ningún beneficio de un sistema operativo), el nombre y el tipo de la función llamada al inicio del programa están definidos por la implementación. Cualquier instalación de biblioteca disponible para un programa independiente, que no sea el conjunto mínimo requerido por la cláusula 4, está definida por la implementación.
El efecto de la finalización del programa en un entorno independiente está definido por la implementación.
La referencia cruzada a la cláusula 4 Conformidad se refiere a esto:
¶5 Un programa estrictamente conforme utilizará solo aquellas características del idioma y la biblioteca especificadas en esta Norma Internacional. 3) No producirá resultados dependientes de ningún comportamiento no especificado, indefinido o definido por la implementación, y no deberá exceder ningún límite mínimo de implementación.
¶6 Las dos formas de implementación conforme son alojadas e independientes . Una implementación hospedada conforme deberá aceptar cualquier programa estrictamente conforme. Una aplicación autoportante conforme aceptará cualquier programa estrictamente conforme en la que el uso de las características especificadas en la cláusula de biblioteca (cláusula 7) se limita al contenido de las cabeceras estándar <float.h>
, <iso646.h>
, <limits.h>
, <stdalign.h>
,
<stdarg.h>
, <stdbool.h>
, <stddef.h>
, <stdint.h>
, y
<stdnoreturn.h>
. Una implementación conforme puede tener extensiones (incluidas funciones de biblioteca adicionales), siempre que no alteren el comportamiento de ningún programa estrictamente conforme. 4)
¶7 Un programa conforme es uno que es aceptable para una implementación conforme. 5)
3) Un programa estrictamente conforme puede usar características condicionales (ver 6.10.8.3) siempre que el uso esté protegido por una directiva de preprocesamiento de inclusión condicional apropiada usando la macro relacionada. Por ejemplo:
#ifdef __STDC_IEC_559__ /* FE_UPWARD defined */
/* ... */
fesetround(FE_UPWARD);
/* ... */
#endif
4) Esto implica que una implementación conforme no reserva identificadores distintos a los reservados explícitamente en esta Norma Internacional.
5) Los programas estrictamente conformes están destinados a ser máximamente portátiles entre implementaciones conformes. Los programas conformes pueden depender de características no portátiles de una implementación conforme.
Es notable que el único encabezado requerido de un entorno independiente que realmente define cualquier función es <stdarg.h>
(e incluso esas pueden ser, y a menudo son, solo macros).
Estándar C ++ - Entorno independiente
Así como el estándar C reconoce tanto el entorno alojado como el independiente, también lo hace el estándar C ++. (Citas de ISO / IEC 14882: 2011.)
1.4 Cumplimiento de implementación [intro.compliance]
¶7 Se definen dos tipos de implementaciones: una implementación alojada y una implementación independiente . Para una implementación alojada, esta Norma Internacional define el conjunto de bibliotecas disponibles. Una implementación independiente es aquella en la que la ejecución puede tener lugar sin el beneficio de un sistema operativo, y tiene un conjunto de bibliotecas definidas por la implementación que incluye ciertas bibliotecas compatibles con el lenguaje (17.6.1.3).
¶8 Una implementación conforme puede tener extensiones (incluidas funciones de biblioteca adicionales), siempre que no alteren el comportamiento de ningún programa bien formado. Se requieren implementaciones para diagnosticar programas que usan tales extensiones que están mal formadas de acuerdo con esta Norma Internacional. Una vez hecho esto, sin embargo, pueden compilar y ejecutar dichos programas.
¶9 Cada implementación incluirá documentación que identifique todas las construcciones soportadas condicionalmente que no admite y define todas las características específicas de la localidad. 3
3) Esta documentación también define el comportamiento definido por la implementación; ver 1.9.
17.6.1.3 Implementaciones independientes [cumplimiento]
Se definen dos tipos de implementaciones: alojadas e independientes (1.4). Para una implementación alojada, esta Norma Internacional describe el conjunto de encabezados disponibles.
Una implementación independiente tiene un conjunto de encabezados definidos por la implementación. Este conjunto debe incluir al menos los encabezados que se muestran en la Tabla 16.
La versión suministrada de la cabecera <cstdlib>
declarará al menos las funciones abort
, atexit
, at_quick_exit
, exit
, y quick_exit
(18.5). Los otros encabezados enumerados en esta tabla deberán cumplir los mismos requisitos que para una implementación hospedada.
Tabla 16 - Encabezados de C ++ para implementaciones independientes
Subclause Header(s)
<ciso646>
18.2 Types <cstddef>
18.3 Implementation properties <cfloat> <limits> <climits>
18.4 Integer types <cstdint>
18.5 Start and termination <cstdlib>
18.6 Dynamic memory management <new>
18.7 Type identification <typeinfo>
18.8 Exception handling <exception>
18.9 Initializer lists <initializer_list>
18.10 Other runtime support <cstdalign> <cstdarg> <cstdbool>
20.9 Type traits <type_traits>
29 Atomics <atomic>
¿Qué pasa con el uso int main()
en C?
El estándar §5.1.2.2.1 del estándar C11 muestra la notación preferida int main(void)
- pero también hay dos ejemplos en el estándar que muestran int main()
: §6.5.3.4 ¶8 y §6.7.6.3 ¶20 . Ahora, es importante tener en cuenta que los ejemplos no son 'normativos'; son solo ilustrativos. Si hay errores en los ejemplos, no afectan directamente el texto principal del estándar. Dicho esto, son muy indicativos del comportamiento esperado, por lo que si el estándar incluye int main()
un ejemplo, sugiere que int main()
no está prohibido, incluso si no es la notación preferida.
6.5.3.4 Los operadores sizeof
y_Alignof
...
¶8 EJEMPLO 3 En este ejemplo, el tamaño de una matriz de longitud variable se calcula y se devuelve desde una función:
#include <stddef.h>
size_t fsize3(int n)
{
char b[n+3]; // variable length array
return sizeof b; // execution time sizeof
}
int main()
{
size_t size;
size = fsize3(10); // fsize3 returns 13
return 0;
}