2010-09-16 17 views
15

He escrito un programa que imprime una tabla. No he incluido la sintaxis de retorno en la función principal, pero aún cuando escribo echo $? 12. muestra¿Por qué una función principal sin una declaración de retorno devuelve el valor 12?

Mi código fuente:

#include <stdio.h> 


int main(void) 
{ 
    int ans,i,n; 
    printf("enter the no. : "); 
    scanf("%d",&n); 

    for(i=1;i<=10;i++) 
    { 
     ans = n*i; 
     printf("%d * %d = %d\n",n,i,ans); 
    } 
} 

no he escrito el 12 de retorno, pero aún así se vuelve 12 cada vez que ejecute el programa.

Gracias.

+1

+1 buena pregunta. :) – Pavitar

+0

http://stackoverflow.com/questions/204476/what-should-main-return-in-c-- y-c –

Respuesta

19

Como dice swegi, es un comportamiento indefinido. Como Steve Jessop y otros dicen que es un comportamiento no especificado antes de C99, y especifica en C99 (el comportamiento observado es no conforme a C99)

Lo que en realidad sucede en la mayoría de ambientes es que el valor de retorno de la última printf se deja en el registro utilizado para los valores de retorno.

Así que será 11 para n == 0, 12 si n es un dígito, 14 de dos dígitos n, 16 para tres dígitos n, etc.

+5

En realidad, es un comportamiento no especificado. –

+0

+1: buena respuesta de plataforma neutral (¿quién tiene una máquina real basada en la pila?;)) – snemarch

+1

(-1, bueno veamos) porque no es un comportamiento indefinido, pero en C89 es específico de la implementación y en C99 el comportamiento que se observa claramente no es conforme. (+1 para una buena explicación de lo que está sucediendo, bueno, tienes suerte) –

1

comportamiento indefinido

+2

De la cancelación del programa 5.1.2.2.3: "Si el tipo de devolución de la función principal es un tipo compatible con int ... llegando a} que termina la función principal devuelve un valor de 0 ". Pero esa especificación parece ser nueva en 'c99' (no en' ansi'). –

+1

@jleedev: el texto 'C89' es similar: "Si el} que termina la función principal se alcanza, el estado de terminación devuelto al entorno del host no se especifica." (src: http://www.vmunix.com/~gabor/c/draft.html) – pmg

+1

@pmg: No me parece muy similar. Uno de ellos afirma un comportamiento específico de implementación, las otras fuerzas devuelven '0'. –

1

Si usted está en todo familiarizado con el lenguaje ensamblador, se recordará que el "valor de retorno" de una función se pasa a través del registro EAX.

En este caso, el valor de retorno se lee de EAX. Que, en este caso, pasa a ser 12.

Sin embargo, no está estableciendo explícitamente este valor, es simplemente un artefacto del resto del código (o tal vez solo una casualidad).

Como se ha dicho, esto es definitivamente undefined behavior. Si simplemente siente curiosidad por los resultados, considere esta explicación.

Pero bajo ningún concepto intente usar intencionalmente este valor como algo significativo.

+6

Esto está restringido a las arquitecturas x86. Pueden ser los más comunes, pero afirmarlo como un hecho universal es definitivamente incorrecto. –

+5

No, esto no es un comportamiento indefinido. Para C89 es específico de implementación y para C99 debe devolverse '0'. –

+0

Bueno, en ARM se puede decir lo mismo sobre r0 – doron

0

Su programa está causando un comportamiento indefinido por no volver cualquier cosa cuando debería, así la persona que llama generalmente tomará lo que sea que el valor del registro eax (en x86, rax en x64) esté en el momento del retorno del procedimiento, que generalmente es basura del último uso de eax (por funciones devueltas valores o simplemente registrar vars basados), en este caso es probablemente la cantidad de caracteres que printf ha escrito en el búfer stdout

18

Respondiendo porque todas las respuestas existentes dicen que es un comportamiento indefinido, lo cual no es cierto, entonces no tengo nada Yo c un voto popular.

En C89 (gracias a PMG En referencia a una draft standard), 5.1.2.2.3:

Un retorno de la llamada inicial a la función principal es equivalente a llamar a la función de salida con el valor devuelto por la función principal como su argumento. Si el} que termina la función principal se alcanza, el estado de terminación devuelto al entorno del host es no especificado.

En C99, citando de n1256, 5.1.2.2.3:

Si el tipo de retorno de la función principal es un tipo compatible con int, un retorno de la llamada inicial a la función principal es equivalente a llamar a la función de salida con el valor devuelto por la función principal como su argumento; al llegar a} que finaliza la función principal devuelve un valor de de 0. Si el tipo de devolución no es compatible con int, el estado de terminación devuelto al entorno de host no está especificado.

Por lo tanto, no es "un comportamiento indefinido": se comporta como si los main devuelve la función, pero en C89 el valor devuelto no está especificado por la norma. Para su programa de ejemplo, en su implementación, el valor devuelto parece ser consistentemente de 12, presumiblemente por el motivo que dice Ben Voigt. Como estás en Linux, probablemente no sea un gran cambio compilar tu código como C99 (o de todos modos, compilarlo usando el modo C99 casi compatible con gcc).

Para cualquier función que devuelve un valor, que no sea main, que es un comportamiento indefinido, a menos la persona que llama no utiliza el valor de retorno (n1256, 6.9.1/12):

Si el} que termina una función es alcanzado, y el valor de la función es utilizado por la persona que llama, el comportamiento no está definido.

No estoy seguro de si la llamada inicial a main se debe mencionar como excluida de esta regla general. No necesita ser: desde el punto de vista del estándar, esa llamada no tiene una persona que llama, por lo que creo que el valor de la llamada a la función no es "utilizado por la persona que llama", aunque se convierta en el estado de finalización para el programa

+2

El estándar actual ISO C de 1990 (y presumiblemente el estándar ANSI de 1989) dice que "el estado de terminación devuelto al entorno de host no está definido". Aparentemente, la palabra se cambió de "no especificado" a "indefinido" entre el borrador y la publicación del estándar. Por cierto, [ese enlace parece estar muerto] (http://www.vmunix.com/~gabor/c/draft.html). –

Cuestiones relacionadas