Неявное int возвращаемое значение функции C

Я искал googled и просто не могу найти ответ на этот простой вопрос.

Работа с устаревшей базой кода (недавно портирована на Linux и медленно обновляется до нового компилятора), и я вижу много

int myfunction(...)
{
// no return...
}

Я знаю, что неявный возвращаемый ТИП функции - это int, но что такое неявное возвращение VALUE, когда возврат не указан. Я тестировал и получил 0, но это только с gcc. Является ли этот компилятор конкретным или стандартным является 0?

EDIT: 12/2017 Скорректированный принятый ответ на основе ссылки на более позднюю версию стандарта.

Ответ 1

Такое возможно, но только в предположении, что возвращаемое значение функции никогда не используется. В стандарте C11 говорится в пункте 6.9.1:

Если функция}, которая завершает функцию, будет достигнута, и значение вызов функции используется вызывающим, поведение undefined.

(предыдущая версия стандарта AFAIR имела аналогичную формулировку)

Итак, было бы неплохо преобразовать все функции такого типа, которые у вас есть для функций void, поэтому у пользователя такой функции не может возникнуть соблазн использовать возвращаемое значение.

Ответ 2

Из стандарта '89, приведенного в новом завещании:

Вытекание конца функции эквивалентно возврату без выражения. В любом случае возвращаемое значение undefined.

Этот стандарт обычно выражает внутреннее поведение ранее существовавших реализаций.

Ответ 3

Это просто поведение undefined; если вы не заселяете область возврата (которая, например, обычно eax/rax на семейных процессорах x86), она будет иметь значение последний установлен через некоторый побочный эффект в вашей функции.

См. Является ли оператор return обязательным для функций С++, которые не возвращают void?, который является в основном дубликатом этого вопроса (за исключением того, что он помечен как С++).

Ответ 4

Оператор return никогда не является обязательным в конце функции, даже если тип возвращаемой функции не является void. Диагностика не требуется, и это не поведение undefined.

Пример (определенное поведение):

int foo(void)
{
}

int main()
{
    foo();
}

Но чтение возвращаемого значения foo - это поведение undefined:

int bla = foo();  // undefined behavior

Из стандарта C:

(C99, 6.9.1p12) "Если функция, которая завершает функцию, достигнута, а значение вызова функции используется вызывающим, поведение undefined."

Функция main является исключением из этого правила, как если бы } был достигнут в main, он эквивалентен, как если бы существовал оператор return 0;.

Ответ 5

Если операторы return последовательно не возвращают значение, функция лучше всего конвертируется и объявляется как возвращающая void:

void myfunction(...)
{
    ...
    return;
    ...
}

Если в этой функции есть несколько операторов return expr; и некоторые return;, тогда вам нужно решить, какое из них лучше, и сделать их согласованными — либо всегда возвращайте значение и оставляйте тип int или никогда не возвращайте значение и не меняете тип на void.

Обратите внимание, что вам нужно объявить функции, измененные для возврата void (в заголовке, если они не являются — или должны быть — static и скрыты в одном исходном файле), поскольку тип возвращаемого по умолчанию ( предполагаемый тип возврата) int больше не действителен.

Ответ 6

В этой функции всегда может быть ноль, но на большинстве архитектур (конечно же, x86) оператор return перемещает содержимое конкретного регистра в определенное место в стеке, которое вызывающий абонент будет извлекать и использовать в качестве функции возврата.

Оператор return поместит переданную ему переменную в это место, чтобы она была другим значением. Мой опыт в том, чтобы не помещать конкретный оператор возврата, состоит в том, что он довольно случайный, что возвращается, и вы не можете полагаться на то, что это одно и то же.

Ответ 7

Я уверен, что это поведение undefined для функции, тип возврата которой не является void, чтобы опустить оператор return. В C99 существует исключение для main, где, если оператор return опущен, предполагается, что он неявно возвращает 0, но это не относится к какой-либо другой функции.

Он может работать с определенной комбинацией платформы/компилятора, но вы никогда не должны полагаться на такие особенности. Использование любого типа поведения undefined в вашем коде делает его не переносимым. Обычно наблюдается поведение undefined в устаревшем коде.