Я просто читал
ISO / IEC 9899: проект комитета 201x - 12 апреля 2011 г.
в котором я нашел в разделе 5.1.2.2.3 Прекращение программы
..reaching the } that terminates the main function returns a value of 0.
это означает, что если вы не укажете какой-либо оператор return в 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);
}
компиляции
gcc test.c
./a.out
sum is 15
echo $?
9 // here it should be 0 but it shows 9 why?
gcc
сам по себе (для версии 4.6.2) компилирует язык, очень похожий, но не совсем похожий на C. Он компилирует GnuC89 - язык, "слабо" основанный на C89.return
оператореsum()
не нужны.int main()
должно бытьint main(void)
.Ответы:
Это правило было добавлено в версию стандарта C. В C90 возвращаемый статус не определен.
Вы можете включить его, перейдя
-std=c99
в gcc.В качестве примечания, что интересно, возвращается 9, потому что это возврат,
printf
который только что написал 9 символов.источник
return 0;
перед закрытием}
. Это безвредно и делает вашу программу переносимой на старые компиляторы.eax
особенно на x86.eax
регистр. См. En.wikipedia.org/wiki/X86_calling_conventions#cdecl для получения дополнительной информации.Он возвращает возвращаемое значение,
printf
которое является количеством действительно распечатанных символов.источник
%errorlevel%
в Windows, есть ли разница между кодом выхода и возвращаемым значениемmain
в Linux?printf
которых в данном случае является 9 , который затем получает «повышен» в качестве кода выхода изmain
при использовании некоторых версий GCC так или иначе.Значение, возвращаемое функцией, обычно сохраняется в регистре eax процессора, поэтому оператор return 4; обычно компилируется в
и вернуть x (в зависимости от вашего компилятора) будет примерно так:
если вы не укажете возвращаемое значение, компилятор все равно выдаст "ret", но не изменит значение eax. Таким образом, вызывающий будет думать, что все, что было ранее оставлено в регистре eax, является возвращаемым значением. В этом примере обычно будет возвращаемое значение printf, но разные компиляторы будут генерировать другой машинный код и по-разному использовать некоторые регистры.
Это упрощенное объяснение, различные соглашения о вызовах и целевые платформы будут играть жизненно важную роль, но этой информации должно быть достаточно, чтобы объяснить, что происходит «за кулисами» в вашем примере.
Если у вас есть базовые представления об ассемблере, стоит сравнить дизассемблирование разных компиляторов. Вы можете обнаружить, что некоторые компиляторы очищают регистр eax в качестве меры предосторожности.
источник