2012-01-13 14 views
21

sé que en los compiladores de C la función main() es llamado por la función _start() que tiene el código algo como esto:¿Qué sucede si main() no devuelve un valor int?

exit(main()); // return value of main is returned 

¿Cómo _start() trabajo cuando main() no vuelve int, por ejemplo, si el tipo de retorno es void , float, o algo más?

+0

Me gustaría fundir el puntero de la función de imagen, pero me gustaría saber de alguien que sepa la verdad. No puedo esperar la respuesta. : D – shinkou

+5

Las restricciones en el valor de retorno de main son diferentes en C y C++ – fefe

+0

@fefe - ¿En serio? Pensé que se requería que ambos regresaran int. ¿Obtuvieron los números de para para leer? Tengo C99 y C++ 89, C++ 11 –

Respuesta

14

Si main no devuelve int, entonces usted tiene un programa mal formado y el comportamiento no está definido. Cualquier cosa puede suceder. Su programa podría fallar, o podría ejecutarse como si nada estuviera mal.

Supongamos que main devolvió algo que no sea int, y su compilador y vinculador permitieron que se realizara el programa. La persona que llama no lo sabe, sin embargo. Si la persona que llama espera que se devuelvan los valores devueltos int en el registro EAX (Intel), entonces eso es lo que leerá para determinar el valor de retorno de main. Si su main defectuoso almacenó allí un valor float, entonces se interpretará como int. (Eso no significa que se truncará. Significa que los bits que componen el diseño de un valor en coma flotante en su lugar conformarán un int). Si su main defectuoso devolvió void, entonces no almacenó nada en el registro esperado, por lo que la persona que llama obtendrá el valor almacenado anteriormente en ese registro.

Si su main devuelve algún tipo que espera almacenar en un lugar que la persona que llama no 'reserva memoria (como una gran estructura), terminará sobrescribiendo algo más, tal vez algo importante para el cierre limpio del programa, haciendo que su programa se cuelgue.

+3

¿Cómo se puede almacenar un flotador en EAX? –

+1

@KerrekSB - Buena pregunta. Sin embargo, antes de 80486 era relativamente común. Después de todo, una carroza es solo 32 bits de material con el que se usan reglas especiales para operar. – Omnifarious

+1

¿Se devuelven los flotadores en los registros, @Kerrek? No lo sé. En el escenario imaginario que describí en mi respuesta, 'main' de hecho, de alguna manera, almacenó un flotador en el lugar donde la persona que llamaba esperaba que fuera un int. ¡El comportamiento no está definido, entonces puedo describir cualquier funcionamiento extraño que quiera! –

8

La función devolverá un valor definido por la implementación. Por ejemplo, en C++, main devuelve implícitamente 0. En este caso de una línea principal void, esto simplemente sería devuelto por _start. Sin embargo, prácticamente no hay implementaciones que permitan ningún tipo de retorno arbitrario: el sistema operativo incluye un proceso que sale con un valor integral.

7

en C++ que sería un error de compilación para volver distinta int nada de main():

error: ‘::main’ must return ‘int’ 

En C es una advertencia, obtendrá un flotador reinterpretada como un int: por ejemplo, 2.1f sería reinterpretado como 224.

+1

FYI, ** gcc ** doesn No dar ninguna advertencia por defecto. – shinkou

+0

@shinkou Acabo de probar gcc - me dio 'advertencia: tipo de devolución de 'main' no es 'int'' – dasblinkenlight

+0

He probado en gcc versión 4.5.2 (64bit) por cierto. – shinkou

0

El estándar C no le permite devolver ningún otro valor que int o void - el compilador c prueba específicamente la firma de main para asegurarse de que sea compatible.

+3

C99 (y lo que vi de los borradores C11) no menciona 'void'. Solo se menciona explícitamente un tipo de retorno de 'int' Se definirá con un tipo de retorno de' int' ', pero desafortunadamente la oración finaliza' o de alguna otra manera definida por la implementación '(5.1.2.2.1) –

+0

Downvoted debido al comentario de retorno nulo 5.1.2.2.1 no menciona nada acerca de los retornos nulos –

+0

@DanielFischer: Creo que el "de alguna otra manera definida por la implementación" se refiere a los parámetros y sus tipos, no al tipo de devolución. – dreamlax

14

El estándar C nunca menciona esta función _start; No creo que C++ lo haga tampoco.

En C antes de la norma ISO 1999, si la ejecución llega al final de main() sin ejecutar una declaración return, o ejecuta una instrucción return que no especifica un valor, a continuación, "el estado de terminación devueltos al entorno de acogida es indefinido ".En la práctica, he visto implementaciones donde dicho programa devuelve un estado de 1 (falla), o algún valor arbitrario en la memoria, como el resultado de la última función que se llamó.

El estándar ISO C de 1999 cambió esto: "Alcanzar el} que termina la función principal devuelve un valor de 0". Esto coincide con la regla de que C++ ha tenido por lo menos desde la primera ISO C++ estándar en 1998.

(Como una cuestión de estilo, prefiero tener una explícita return 0; al final de main, incluso si no es estrictamente necesario. esto es consistente con int funciones distintas de main, y hace que para una mejor portabilidad para pre-C99 compiladores de C.)

Todo esto supone que main se define con un tipo de retorno de int. Es el único tipo específicamente compatible con el estándar C (int main(void) o int main(int argc, char *argv[]) o equivalente), pero las implementaciones (alojadas) pueden admitir otras definiciones definidas por la implementación. El estándar C90 no cubre explícitamente este caso, pero C99 dice: "Si el tipo de devolución no es compatible con int, el estado de terminación devuelto al entorno del host no está especificado".

El estándar C++ es un poco diferente. Para las implementaciones alojadas, se debe definir main para devolver int. Los parámetros están definidos por la implementación, pero ambas formas estándar de C deben ser compatibles.

Para una implementación alojada en C o C++, no hay una buena razón que conozca para definir main con un tipo de devolución que no sea int. Solo use una de las dos definiciones estándar, y la pregunta no surgirá.

Para "implementaciones independientes", "el nombre y tipo de la función llamada en el programa de inicio están definidos por la implementación". Por lo tanto, el punto de entrada podría legítimamente devolver void u otra cosa, y es posible que ni siquiera se llame main. Tenga en cuenta que una "implementación independiente" es una "en la que la ejecución del programa C puede tener lugar sin ningún beneficio de un sistema operativo", típicamente un sistema integrado.

+0

¿No consideraría el desarrollo del núcleo del sistema como una "implementación independiente" según esa definición? Por supuesto, si un núcleo del sistema operativo llega al final de la función de punto de entrada, tiene un problema ... –

+0

@ MichaelKjörling: Probablemente. En la práctica, una implementación es "independiente" si el implementador dice que es (y cumple con los requisitos más débiles para las implementaciones independientes). –

+0

@KeithThompson: antes de C99 si la ejecución llega al final de main() sin ejecutar una declaración de devolución, o ejecuta una declaración de devolución que no especifica un valor, entonces "el estado de terminación devuelto al entorno de host no está especificado" no definido . – Destructor

2

Implementaciones estándar de C esperan main para devolver int simplemente porque así se define en el estándar C. Devolver algo que no sea int (o un tipo compatible con int) generalmente resulta en un comportamiento indefinido —, lo que significa que no hay forma de saber qué sucederá.

Sin embargo, existen implementaciones no estándar de C, por ejemplo, el sistema operativo Plan 9 utiliza void main(), here es una lista de sus utilidades ' código fuente. El código C de Plan 9 es bastante diferente a K & R, ANSI, C99 o C11. Here's un enlace que explica cómo el Plan 9 usa el lenguaje C.

2

Si el tipo de devolución de main no es un int, entonces el valor de retorno es la implementación definida.
En resumen, se permite que una Implementación tenga un tipo de devolución diferente a int para main, pero ninguna de las implementaciones conocidas admite otra cosa que no sea int.
Idealmente, deberá consultar la documentación de su plataforma y del compilador para ver qué comportamiento exacto define, ya que está permitido que la flexibilidad lo permita el estándar.

Referencia:

C++ 03 estándar:

3.6.1 Función principal [basic.start.main]

Una implementación no deberá definir previamente la función principal . Esta función no debe estar sobrecargada. Tendrá un tipo de retorno de tipo int, pero de lo contrario su tipo está definido por la implementación. Todas las implementaciones permitirán ambas de las siguientes definiciones de principal:

int main() {/ * ... * /}

y

int main (int argc, char * argv []) {/ * ... * /}

.....

+0

¿No significa que debe tener un tipo de retorno 'int', pero aparte de eso puede tomar cualquier argumento, siempre que la implementación no permita argumentos y' argc'/'argv' (es decir, el * tipo de retorno * es 'int', pero el tipo de la función' main' está definido por la implementación). Estoy esperando que el café se instale, así que tal vez no tenga ningún sentido ... – dreamlax

0

Supongamos que estamos utilizando Visual Studio 2012.

Para progr C++ ams, Visual Studio permite que void se especifique como el tipo de devolución, aunque esto está prohibido por el estándar de C++. Según el estándar, main() debe devolver un int en implementaciones alojadas.

Para los programas C, se permite cualquier tipo de devolución para main(), pero la devolución de algo que no sea int da como resultado un comportamiento no especificado. Por ejemplo, en Visual Studio 2012, al devolver 0.0 de double main() se obtiene un valor de retorno de 0xcccccccc cuando el programa se ejecuta en el depurador (consulte In Visual Studio C++, what are the memory allocation representations?).

Cuestiones relacionadas