2012-04-09 1 views
21

Я googled и просто не могу найти ответ на этот простой вопрос.Implicit int возвращает значение функции C

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

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

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

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

+0

попытайтесь скомпилировать с -Wall -O3 и без -g. Попытайтесь узнать, осталось ли возвращаемое значение 0, и если существует какое-то предупреждение – kappa

+1

Попробуйте скомпилировать с '-Wall -Werror' и посмотреть, все еще компилируется. – dreamlax

+0

Принятый ответ следует изменить. Цитата 89 версия стандарта находится вне своего места в 2016 году. –

ответ

7

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

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

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

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

+0

Хорошо, вы говорите, что **, пока мы его не читаем **, поведение программы все еще в порядке? – Pacerier

+0

Да, стандарт говорит, что. –

+0

Ну, первый ответ dmckee, похоже, противоречит этому. – Pacerier

20

От стандарта '89 в цитируемой в Новом Завете:

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

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

+0

Вы имеете в виду, что только значение не определено или что поведение программы не определено после этой точки? – Pacerier

+0

В стандарте 89 не указывается. Я бы предположил, что фактические компиляторы не будут вас удивлять, если вы не попытаетесь использовать возвращаемое значение. Но никто этого не гарантирует. – dmckee

+0

Что [о C11] (http://stackoverflow.com/a/10079437/632951), то? – Pacerier

10

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

См. Is a return statement mandatory for C++ functions that do not return void?, который является в основном дубликатом этого вопроса (за исключением того, что он помечен как C++).

+0

+1 для упоминания 'x86',' rax' и 'eax'.<3 –

+1

Не совсем, это только UB, если используется возвращаемое значение, что, вероятно, не так, см. Мой ответ. –

+1

Да, это не неопределенное поведение, если вы не прочитаете значение возврата. См. Мой ответ. – ouah

0

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

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

1

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

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

2

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

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

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

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

6

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

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

int foo(void) 
{ 
} 

int main() 
{ 
    foo(); 
} 

Но чтение возвращаемое значение foo не определено поведение:

int bla = foo(); // undefined behavior 

От C стандарт:

(С99, 6,9 .1p12) «Если функция, которая завершает функцию, будет достигнута, а значение вызова функции используется вызывающим, поведение не определено ».

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

+1

* «и это не неопределенное поведение» *, если вызывающий абонент не использует возвращаемое значение. – dmckee

+3

@dmckee Вот почему я написал: * «Но чтение возвращаемого значения foo - неопределенное поведение» * – ouah

 Смежные вопросы

  • Нет связанных вопросов^_^