2011-12-30 4 views
116

Je viens de lirePourquoi la fonction principale ne renvoie pas 0 ici?

ISO/IEC 9899: Comité 201x Projet - 12 Avril, 2011

où je l'ai trouvé sous 5.1.2.2.3 la fin du programme

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

cela signifie si vous ne spécifiez aucune instruction de retour dans main(), et si le programme s'exécute avec succès, alors à l'accolade de fermeture} de main retournera 0.

Mais dans le foll Code du fait que je ne spécifiez aucune instruction de retour, mais il ne retourne pas 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); 
} 

compilez

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

Avez-vous compilé avec un compilateur C99 (ou supérieur)? – pmg

+69

+1 pour avoir la patience de lire les spécifications ..... – Asher

+0

J'ai compiler avec gcc sans option/drapeau supplémentaire? –

Répondre

140

Cette règle a été ajoutée dans la version 1999 de la norme C. En C90, le statut renvoyé est indéfini.

Vous pouvez l'activer en transmettant -std=c99 à gcc.

En note, il est intéressant de noter que 9 est retourné car c'est le retour de printf qui vient d'écrire 9 caractères.

+8

merci. gcc -std = c99 test.c donne 0 –

+40

Ou vous pouvez simplement ajouter 'return 0;' avant la fermeture '}'. C'est inoffensif et rend votre programme portable pour les compilateurs plus anciens. –

+0

does} de la main retournera 0 est ajouté dans c99 ou sa partie de l'ancienne version de c? –

15

Renvoie la valeur de retour printf qui est le nombre de caractères réellement imprimés.

+0

la question ne parle pas de ce qui est imprimé dans la console lors de l'exécution du programme, il parle de la valeur de retour du programme: (vous pouvez l'obtenir dans Linux avec la commande schell: echo $? Et dans windows avec: echo% errorlevel%) –

+1

@eharvest Bien que je ne sais pas comment vérifier '% errorlevel%' dans Windows, une différence entre le code de sortie et la valeur de retour de 'main' sous linux? –

+1

@eharvest: La réponse ne parle pas de ce qui est imprimé dans la console aussi. Il parle du _return value_ de 'printf' qui dans ce cas est 9 qui devient alors" promu "comme le code de sortie de' main' quand on utilise certaines versions de gcc. –

6

La valeur de retour d'une fonction est normalement stockée dans le registre eax du processeur, de sorte que l'instruction "return 4;" compilerait habituellement

mov eax, 4; 
ret; 

et retour x (selon votre compilateur) serait quelque chose comme:

mov eax, [ebp + 4]; 
ret; 

si vous ne spécifiez pas une valeur de retour alors le compilateur encore cracher le " ret "mais ne change pas la valeur de eax. Ainsi, l'appelant pensera que tout ce qui reste dans le registre eax est la valeur de retour. Pour cet exemple, il s'agira généralement de la valeur de retour printf, mais différents compilateurs généreront un code machine différent et utiliseront différemment certains registres. Ceci est une explication simplifiée, les différentes conventions d'appel et les plates-formes cibles joueront un rôle essentiel, mais il devrait y avoir suffisamment d'informations pour expliquer ce qui se passe derrière la scène dans votre exemple.

Si vous avez une compréhension de base de l'assembleur, cela vaut la peine de comparer le démontage de différents compilateurs. Vous pouvez constater que certains compilateurs effacent le registre eax comme une sauvegarde.

+11

Le compilateur _might_ fait cela. C'est indéfini. Il peut choisir de vous tirer dans la tête avec une cartouche d'imprimante. –

+0

@LightnessRacesinOrbit indéfini n'est pas la même chose qu'imprévisible, c'est-à-dire "si le compilateur fait X, il sera conforme" il ne suit pas logiquement "le compilateur pourrait faire X" – Owen

+0

@Owen: Citez le passage standard définissant ceci. –