Оператор return в C — это инструкция, которая немедленно завершает выполнение текущей функции и передает управление обратно в точку вызова, а при наличии выражения — еще и возвращает его значение. Ниже разберем, что именно возвращает return, как он работает в обычной и в void-функции, зачем нужен ранний выход и чем return отличается от break, continue и exit.
Содержание
Материал рассчитан на тех, кто начинает писать на C. Все примеры — готовые программы, которые можно скопировать и скомпилировать (например, gcc file.c -o prog && ./prog).
Что возвращает return
return отдает одно значение в ту функцию, которая вызвала текущую. Тип этого значения приводится к типу, объявленному у функции. Если функция объявлена как int, вернется целое; если как double — дробное.
Приведение делается автоматически и может терять данные. Внутри функции с типом int запись return 3.9; вернет 3 — дробная часть отбрасывается. Внутри функции с типом double запись return 3; вернет 3.0.
Важно: в C возврат идет по значению — наружу уходит копия. Чтобы вернуть много данных или большой массив, обычно возвращают структуру или указатель, а не копируют все поэлементно.
Если функция должна вернуть значение (тип не void), но управление дошло до закрывающей скобки без return, возвращаемое значение не определено. Вызвавший код получит мусор, поэтому return в не-void функции обязателен на всех путях выполнения.
Синтаксис и как это работает
Форм записи две:
return выражение; // завершить функцию и вернуть значение выражения
return; // завершить функцию без возврата значения (только для void)
При обработке return происходит три вещи по порядку:
- Выполнение текущей функции прекращается сразу же.
- Значение выражения (если оно есть) приводится к типу возврата и передается в точку вызова.
- Управление возвращается в вызвавшую функцию, на место сразу после вызова.
Инструкции, написанные после сработавшего return, не выполняются — это недостижимый код. В одной функции может быть несколько return (например, в разных ветках if); сработает первый, до которого дойдет управление, остальные будут пропущены.
Отдельный случай — return в функции main. Он завершает программу и передает код в операционную систему: return 0; — признак успешного завершения, ненулевой код — признак ошибки. Начиная со стандарта C99, если управление доходит до конца main без return, компилятор сам подставляет return 0;.
Минимальный рабочий пример на C
Начнем с целой программы, которую можно запустить, а потом разберем ее по строкам.
#include <stdio.h>
// Возвращает наибольшее из двух целых
int max2(int a, int b) {
if (a > b) {
return a; // ранний выход: до второго return дело не дойдет
}
return b;
}
int main(void) {
int m = max2(7, 3);
printf("max2(7, 3) = %d\n", m);
return 0; // 0 - код успешного завершения программы
}
// --- конец примера ---
Вывод в консоли:
max2(7, 3) = 7
Что здесь происходит по шагам:
max2объявлена с типомint, значит обязана вернуть целое на любом пути.- При вызове
max2(7, 3)условиеa > bистинно, срабатываетreturn a;— функция немедленно завершается и отдает7. - Второй
return b;в этом вызове недостижим: до него управление не доходит. - Возвращенное значение записывается в переменную
m, иprintfпечатает7. return 0;вmainзавершает программу с кодом успеха.
Вывод этого примера не зависит от компилятора и операционной системы — он определен только логикой кода.
return в void-функции: просто выход
Если функция объявлена как void, она ничего не возвращает. Здесь return не отдает значение — он лишь досрочно прекращает работу функции. Форма только одна: return; без выражения. Попытка написать return что-то; в void-функции — ошибка компиляции.
Такой return удобен для раннего выхода: проверяем условие в начале и, если делать нечего, выходим, не заходя в основной код.
#include <stdio.h>
// Печатает число, только если оно положительное
void print_if_positive(int x) {
if (x <= 0) {
return; // ранний выход из void-функции: значение не возвращается
}
printf("положительное: %d\n", x);
}
int main(void) {
print_if_positive(-5); // условие сработало, функция вышла молча
print_if_positive(42); // напечатает строку
return 0;
}
// --- конец примера ---
Вывод:
положительное: 42
Первый вызов ничего не печатает: x <= 0, сработал return;, и до printf управление не дошло. Такой прием (ранняя проверка и выход) называют охранным условием — он убирает лишнюю вложенность if и делает код плоским и читаемым.
Чем return отличается от break, continue и exit
Эти операторы часто путают, потому что все они меняют обычный ход выполнения. Но действуют они на разных уровнях: return — на уровне функции, break и continue — на уровне цикла, exit — на уровне всей программы.
| Оператор | Что делает | Где применяется | Куда уходит управление |
|---|---|---|---|
return |
завершает текущую функцию, отдает значение в точку вызова | в любой функции | в вызвавшую функцию |
break |
прерывает ближайший цикл или switch |
внутри for/while/do-while/switch |
на строку после цикла или switch |
continue |
пропускает остаток текущей итерации | внутри цикла | к проверке условия цикла (следующая итерация) |
exit |
немедленно завершает всю программу | где угодно, нужен #include <stdlib.h> |
в операционную систему |
Практический ориентир: break и continue управляют одним циклом и не выходят из функции; return выходит из функции целиком (и из цикла заодно, если был внутри него); exit(код) не возвращает управление никуда внутри программы — процесс завершается. В main запись return 0; по эффекту близка к exit(0).
Частые ошибки
Разберем три типовые ошибки в формате «неверный код -> результат -> как исправить».
1. return без значения в не-void функции.
int get_answer(void) {
return; // функция объявлена int, а значение не отдано
}
Результат при сборке gcc -Wall:
warning: 'return' with no value, in function returning non-void [-Wreturn-type]
Исправление — вернуть значение нужного типа: return 42;. На части компиляторов (например, Clang) это не предупреждение, а ошибка компиляции — сборка не пройдет, пока функция не вернет значение.
2. Пропущенный return в не-void функции.
int square(int x) {
int r = x * x;
// забыли вернуть r
}
Результат gcc -Wall:
warning: control reaches end of non-void function [-Wreturn-type]
Вызвавший код получит непредсказуемое значение. Исправление — добавить return r; в конце.
3. Недостижимый код после return.
int f(void) {
return 1;
printf("сюда управление не дойдет\n"); // мертвый код
}
Строка после return 1; не выполнится никогда: return уже завершил функцию. Компилятор может пропустить это молча (clang с флагом -Wunreachable-code предупредит). Исправление — убрать мертвый код или перенести нужные действия до return.
Выводы
- return немедленно завершает функцию и передает управление в точку вызова; код после сработавшего return не выполняется.
- В не-void функции return обязан вернуть значение на каждом пути; иначе вызвавший получит неопределенный результат.
- Возвращаемое значение приводится к типу функции, поэтому
int-функция обрежет дробную часть, аdouble-функция превратит целое в дробное. - В void-функции return не возвращает значение, а просто досрочно выходит; это удобный ранний выход через охранное условие.
- return, break, continue и exit работают на разных уровнях: функция, цикл, цикл, программа — их нельзя заменять друг другом.
- В
mainreturn передает код завершения в операционную систему:0— успех, ненулевой — ошибка.
Где применяется / связь с практикой
Возврат значений — основа любой программы на C: функции получают данные, обрабатывают и отдают результат через return, а main через него сообщает системе код завершения. Без уверенного понимания return сложно писать функции, разбивать программу на части и обрабатывать ошибки.
Освойте тему на практике
Отработать это на практике, с проверкой преподавателя, можно на курсе C++ для начинающих: там разбираются функции, возврат значений, работа с памятью и синтаксис, общий у C и C++. Посмотреть формат занятий и задать вопросы преподавателю можно на бесплатных вебинарах — это открытые уроки без оплаты.
Смежные темы: Язык C: области применения, Условный оператор IF: принципы работы, C++: описание языка и его основы.
FAQ
Сколько return может быть в одной функции?
Сколько угодно — например, свой return в каждой ветке if. Сработает первый, до которого дойдет управление, остальные будут пропущены.
Обязателен ли return 0; в конце main в современном C?
Нет. По стандарту C99 и новее, если управление доходит до конца main без return, компилятор сам подставляет возврат 0. Явный return 0; все же полезен для читаемости.
return копирует значение или отдает ссылку на переменную функции?
В C возврат идет по значению — наружу уходит копия, а локальные переменные функции уже уничтожены. Возвращать адрес локальной переменной нельзя; чтобы отдать много данных, возвращают структуру или указатель на память, живущую дольше вызова.



