Почему main не возвращает 0 здесь? - PullRequest
116 голосов
/ 30 декабря 2011

Я только что прочитал

ИСО / МЭК 9899: проект комитета 201x - 12 апреля 2011 г.

, в котором я нашел в разделе 5.1.2.2.3 Завершение программы

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

это означает, что если вы не укажете какой-либо оператор возврата в main(), и если программа успешно выполнится, то при закрывающей скобке} main вернет 0.

Но в следующем коде я не указываю никакого оператора возврата, но он не возвращает 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);
}

compile

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

Ответы [ 3 ]

140 голосов
/ 30 декабря 2011

Это правило было добавлено в версию стандарта С 1999 года. В C90 возвращаемый статус не определен.

Вы можете включить его, передав -std=c99 в gcc.

В качестве примечания, интересно, что возвращается 9, потому что это возвращение printf, которое только что написало 9 символов.

15 голосов
/ 30 декабря 2011

Возвращает возвращаемое значение printf, которое является количеством действительно напечатанных символов.

6 голосов
/ 03 января 2012

Возвращаемое значение из функции обычно сохраняется в регистре eax процессора, поэтому оператор «return 4;»обычно компилируется в

mov eax, 4;
ret;

, а return x (в зависимости от вашего компилятора) будет выглядеть примерно так:

mov eax, [ebp + 4];
ret;

, если вы не укажете возвращаемое значение, компилятор все равно будетвыплюнуть "ret", но не изменяет значение eax.Таким образом, вызывающий объект будет думать, что то, что когда-либо ранее оставалось в регистре eax, является возвращаемым значением.Для этого примера это обычно будет возвращаемое значение printf, но разные компиляторы будут генерировать разный машинный код и по-разному использовать некоторые регистры.

Это упрощенное объяснение, различные соглашения о вызовах и целевые платформы будут играть важную роль, нов вашем примере должно быть достаточно информации, чтобы объяснить, что происходит «за кулисами».

Если у вас есть базовое понимание ассемблера, стоит сравнить разборку различных компиляторов.Вы можете обнаружить, что некоторые компиляторы очищают регистр eax в качестве меры безопасности.

...