Solo estaba leyendo
ISO / IEC 9899: Borrador del Comité 201x - 12 de abril de 2011
en el que encontré en 5.1.2.2.3 Terminación del programa
..reaching the } that terminates the main function returns a value of 0.
significa que si no especifica ninguna declaración de retorno en main()
, y si el programa se ejecuta correctamente, en la llave de cierre} de main devolverá 0.
Pero en el siguiente código no especifico ninguna declaración de devolución, pero 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?
gcc
por sí mismo (para la versión 4.6.2) compila un lenguaje muy similar pero no del todo parecido a C. Compila GnuC89 - un lenguaje "libremente" basado en C89.return
declaración ensum()
son innecesarios.int main()
debería serint main(void)
.Respuestas:
Esa regla se agregó en la versión de 1999 del estándar 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 el regreso del
printf
cual solo se escribieron 9 caracteres.fuente
return 0;
antes del cierre}
. Es inofensivo y hace que su programa sea portátil para compiladores más antiguos.eax
específicamente en x86.eax
registro. Consulte en.wikipedia.org/wiki/X86_calling_conventions#cdecl para obtener más información.Devuelve el valor de retorno del
printf
cual es el número de caracteres realmente impresos.fuente
%errorlevel%
en Windows, ¿alguna diferencia entre el código de salida y el valor de retorno demain
en Linux?printf
que en este caso es 9, que luego se "promueve" como el código de salida demain
alguna manera cuando se usan ciertas versiones de gcc.El valor de retorno de una función normalmente se almacena en el registro eax de la CPU, por lo que la instrucción "return 4;" normalmente se compilaría para
y devolver x (dependiendo de su compilador) sería algo como:
si no especifica un valor de retorno, el compilador todavía escupirá el "ret" pero no cambiará 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, 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 un conocimiento básico del ensamblador, vale la pena comparar el desensamblaje de diferentes compiladores. Puede encontrar que algunos compiladores están limpiando el registro eax como medida de seguridad.
fuente