Почему основная функция без возвращаемого оператора возвращает значение 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