Функция C, определенная как int, но не имеющая оператора возврата в теле, все еще компилируется - PullRequest
15 голосов
/ 23 ноября 2010

Скажем, у вас есть код C, подобный следующему:

#include <stdio.h>

int main(){
    printf("Hello, world!\n");
    printf("%d\n", f());    
}

int f(){

}

Он прекрасно компилируется с помощью gcc, и вывод (в моей системе):

Привет, мир!

14

Но ... но ... как это возможно?Я думал, что C не позволит вам скомпилировать что-то подобное, потому что f () не имеет оператора return, возвращающего целое число.Почему это разрешено?Это функция C или упущение компилятора, и откуда взялось 14?

Ответы [ 7 ]

17 голосов
/ 23 ноября 2010

Возвращаемое значение в этом случае, в зависимости от конкретной платформы, скорее всего, будет любым случайным значением, оставленным в регистре возврата (например, EAX на x86) на уровне сборки.Не допускается явное возвращение значения, но оно дает неопределенное значение.

В этом случае значение 14 - это возвращаемое значение из printf.

9 голосов
/ 23 ноября 2010

скомпилируйте с -Wall, чтобы включить дополнительную проверку работоспособности в компиляторе.

gcc -Wall /tmp/a.c
/tmp/a.c: In function ‘main’:
/tmp/a.c:5: warning: implicit declaration of function ‘f’
/tmp/a.c:6: warning: control reaches end of non-void function
/tmp/a.c: In function ‘f’:
/tmp/a.c:10: warning: control reaches end of non-void function

Обратите внимание, как он отмечает отсутствующие операторы возврата - как "управление достигает конца функции, не являющейся пустым"?

Всегда компилируйте, используя -Wall или аналогичный - вы сэкономите душевную боль позже.


Я могу вспомнить несколько случаев, когда именно эта проблема приводила к исправлению часов или дней отладки - это как быработает, пока не сработает.

4 голосов
/ 30 марта 2012

14 также является возвращаемым значением первого printf.Возможно, компилятор оптимизировал вызов функции f (), и в EAX у нас осталось 14.

Попробуйте скомпилировать код с разными уровнями оптимизации (-O0, -O1, -O2, -O3,И посмотрите, не изменится ли выход.

2 голосов
/ 19 апреля 2012

18 - это возвращаемое значение первого оператора печати. (количество напечатанных символов)

Это значение хранится в памяти стека.

Во второй функции printf значение стека «возвращается» функцией f. Но f просто оставил значение, которое printf создал в этом слоте, в стеке.

например, в этом коде:

#include <stdio.h>

int main(){
    printf("Hello, world!1234\n");
    printf("%d\n", f());    
}

int f(){

}

Что хорошо компилируется с gcc, и вывод (на моей системе):

Привет, мир!

18

для деталей printf() возвращаемое значение напишите мне.

1 голос
/ 23 ноября 2010

Вероятно, у вас очень низкий уровень предупреждения вашего компилятора. Так что это разрешено, даже если результат не определен.

1 голос
/ 23 ноября 2010

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

Таким образом, пропуск оператора возврата разрешен, но неопределенное значение будет возвращено, если вы попытаетесьиспользуйте это.

0 голосов
/ 24 ноября 2010

Я компилирую с -Werror=return-type, чтобы предотвратить это.GCC выдаст ошибку, если вы не вернетесь из функции (если это не возврат по void).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...