Почему основная функция без возвращаемого оператора возвращает значение 12?
Я написал программу, которая печатает таблицу. Я не включил синтаксис возврата в основную функцию, но все же, когда я набираю echo $? он отображает 12.
Мой исходный код:
#include <stdio.h>
int main(void)
{
int ans,i,n;
printf("enter the no. : ");
scanf("%d",&n);
for(i=1;i<=10;i++)
{
ans = n*i;
printf("%d * %d = %d\n",n,i,ans);
}
}
Я не написал ответ 12, но все равно он возвращает 12 каждый раз, когда я запускаю программу.
Спасибо.
Ответы
Ответ 1
Как говорит Swegi, это неопределенное поведение. Как говорят Стив Джессоп и др., Это неопределенное значение до C89 и указано в C99 (наблюдаемое поведение не соответствует C99)
Что в действительности происходит в большинстве сред, так это то, что возвращаемое значение из последнего printf
остается в регистре, используемом для возвращаемых значений.
Таким образом, будет 11 для n == 0, 12, если n одна цифра, 14 для двух цифр n, 16 для трех цифр n и т.д.
Ответ 2
Отвечая на то, что все существующие ответы говорят, что это поведение undefined, что неверно, поэтому у меня нет ничего, что можно было бы поддержать.
В C89 (благодаря pmg для ссылки на черновик стандарта), 5.1.2.2.3:
Возврат от начального вызова к основная функция эквивалент вызова функции выхода со значением возвращенный главной функцией в качестве аргумента. Если} который завершает выполнение основной функции, статус завершения, возвращаемый в среду хоста, не определено.
В C99, цитируя из n1256, 5.1.2.2.3:
Если тип возврата основного функция - это тип, совместимый с int, возврат от первоначального вызова до основная функция эквивалентна вызов функции выхода с помощью значение, возвращаемое главной функцией как его аргумент; достигая}, что завершает основную функцию, возвращает значение 0. Если тип возврата не является совместим с int, завершение статус, возвращенный хосту среда не указана.
Итак, это не "поведение w91 > ": он ведет себя так, как будто функция main
возвращается, но в C89 возвращаемое значение не указывается стандартом. Для вашей примерной программы, по вашей реализации, возвращаемое значение, по-видимому, должно быть 12, предположительно по той причине, о которой говорит Бен Фойгт. Поскольку вы работаете в Linux, вероятно, это не большое изменение для компиляции вашего кода как C99 (или, во всяком случае, скомпилируйте его с использованием gcc почти совместимого режима C99).
Для любой функции, которая возвращает значение, отличное от main
, это поведение undefined, если вызывающий объект не использует возвращаемое значение (n1256, 6.9.1/12):
Если функция}, которая завершает функцию, и значение функции вызов используется вызывающим абонентом, поведение undefined.
Я не уверен, следует ли упоминать первоначальный вызов main
как исключенный из этого общего правила. Это не должно быть: из POV стандарта, этот вызов не имеет вызывающего абонента, поэтому я думаю, что значение вызова функции не "используется вызывающим", даже если оно становится статусом завершения для программы.
Ответ 3
undefined поведение
Ответ 4
Если вы хорошо знакомы с языком ассемблера, вы можете вспомнить, что "возвращаемое значение" функции передается через регистр EAX.
В этом случае возвращаемое значение считывается из EAX. Который в этом случае составляет 12.
Однако вы не устанавливаете это значение явно, это просто артефакт из остальной части кода (или, возможно, просто шанс).
Как уже было сказано, это определенно undefined behavior
. Если вам просто интересно, почему это так, рассмотрите это объяснение.
Но ни при каких обстоятельствах не пытайтесь умышленно использовать это значение как что-либо значимое.
Ответ 5
Ваша программа вызывает поведение undefined, не возвращая что-либо, когда это необходимо, поэтому вызывающий объект обычно захватывает то, что когда-либо значение регистра eax (на x86, rax на x64) находится во время возврата процедуры, который, как правило, является мусором из последнего использования eax (возвращаемые значениями функций или только регистровые вары), в этом случае, вероятно, количество char, которое printf записано в буфер stdout