¿Por qué main no devuelve 0 aquí?


Estaba leyendo

ISO / IEC 9899: Borrador del Comité 201x-Abril 12, 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 instrucción return en main(), y si el programa se ejecuta correctamente, entonces en la llave de cierre } de main devolverá 0.

Pero en el siguiente código no especifico ninguna instrucción return, 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?
Author: Jeegar Patel, 2011-12-30

3 answers

Esa regla fue añadida en la versión de 1999 del estándar C. En C90, el estado devuelto es indefinido.

Puede activarlo pasando -std=c99 a gcc.

Como nota al margen, curiosamente 9 se devuelve porque es el retorno de printf que acaba de escribir 9 caracteres.

 140
Author: cnicutar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-12-30 08:46:03

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

 15
Author: Summer_More_More_Tea,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-12-30 08:45:39

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 en

mov eax, 4;
ret;

Y return x (dependiendo de su compilador) sería algo así como:

mov eax, [ebp + 4];
ret;

Si no especifica un valor devuelto, el compilador seguirá escupiendo el "ret" pero no cambia el valor de eax. Por lo tanto, la persona que llama pensará que lo que quedó en el registro eax anteriormente es el valor devuelto. Para este ejemplo sería normalmente es el valor de retorno printf, pero diferentes compiladores generarán código de máquina diferente 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 las escenas' en su ejemplo.

Si tienes una comprensión básica de ensamblador vale la pena comparar el desmontaje de diferentes compiladores. Usted puede encontrar que algunos los compiladores están limpiando el registro eax como una salvaguardia.

 6
Author: noggin182,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-01-03 17:58:13