2011-12-30 31 views
116

Estaba leyendo¿Por qué main no devuelve 0 aquí?

ISO/IEC 9899: 201x Comité Proyecto - 12 de abril 2011

en el que he encontrado por resolución 5.1.2.2.3 Programa

..reaching the } that terminates the main function returns a value of 0. 

que significa si no especifica ninguna declaración de devolución en main(), y si el programa se ejecuta con éxito, entonces en el corchete de cierre} de main devolverá 0.

Pero a la vista debido código que no se especifica ninguna instrucción de retorno, sin embargo, no devuelve 0

#include<stdio.h> 
int sum(int a,int b) 
{ 
return (a + b); 
} 

int main() 
{ 
    int a=10; 
    int b=5; 
    int ans;  
    ans=sum(a,b); 
    printf("sum is %d",ans); 
} 

compilar

gcc test.c 
./a.out 
sum is 15 
echo $? 
9   // here it should be 0 but it shows 9 why? 
+0

¿Compiló con un compilador C99 (o superior)? – pmg

+69

+1 por tener la paciencia de leer las especificaciones ..... – Asher

+0

tengo compilación con gcc sin opción/bandera adicional? –

Respuesta

140

se añadió Esa regla en la versión 1999 de la norma C. En C90, el estado devuelto no está definido.

Puede habilitarlo pasando -std=c99 a gcc.

Como nota al margen, curiosamente se devuelve 9 porque es la devolución de printf que acaba de escribir 9 caracteres.

+8

gracias. gcc -std = c99 test.c da 0 –

+40

O simplemente puede agregar 'return 0;' antes del cierre '}'. Es inofensivo y hace que tu programa sea portátil para compiladores más antiguos. –

+0

does} of main will return 0 se agrega en c99 o forma parte de la versión anterior de c? –

15

Devuelve el valor de retorno de printf que es el número de caracteres realmente impreso.

+0

la pregunta no habla sobre lo que está impreso en la consola cuando se ejecuta el programa, sino que habla del valor de retorno del programa: (puede obtenerlo en Linux con el comando schell: echo $? Y en ventanas con: echo% errorlevel%) –

+1

@eharvest Aunque no sé cómo comprobar '% errorlevel%' en Windows, ¿hay alguna diferencia entre el código de salida y el valor de retorno de 'main' en Linux? –

+1

@eharvest: La respuesta no habla sobre lo que está impreso en la consola también. Habla sobre el valor _return_ de 'printf' que en este caso es 9, que luego se" promociona "como el código de salida de' main' de alguna manera cuando se usan ciertas versiones de gcc. –

6

El valor de retorno de una función normalmente se almacena en el registro eax de la CPU, por lo que la declaración "return 4;" por lo general a compilar

mov eax, 4; 
ret; 

yx (dependiendo de su compilador) volver sería algo así como:

mov eax, [ebp + 4]; 
ret; 

si no se especifica un valor de retorno, entonces el compilador todavía escupir el " ret "pero no cambia el valor de eax. Entonces la persona que llama pensará que lo que quedó en el registro eax anteriormente es el valor de retorno. Para este ejemplo, normalmente sería el valor de retorno printf, pero diferentes compiladores generarán diferentes códigos de máquina y usarán algunos registros de manera diferente.

Esta es una explicación simplificada, las diferentes convenciones de llamadas y plataformas de destino jugarán un papel vital, pero debería ser suficiente información para explicar lo que está sucediendo "detrás de escena" en su ejemplo.

Si tiene una comprensión básica del ensamblador, vale la pena comparar el desmontaje de diferentes compiladores. Puede encontrar que algunos compiladores están borrando el registro eax como salvaguarda.

+11

El compilador _might_ hacer eso. No está definido En su lugar, puede elegir dispararle en la cabeza con un cartucho de impresora. –

+0

@LightnessRacesinOrbit undefined no es lo mismo que impredecible, es decir, desde "si el compilador hace X, será conforme estándar", no sigue lógicamente "el compilador podría hacer X" – Owen

+0

@Owen: Cita el pasaje estándar que define esto. –

Cuestiones relacionadas