Неявное 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 в устаревшем коде.