Что должна возвращать main() в C++? Сравнение с C и стандарты

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Введение: Главный вопрос, который задают даже профи

Вы когда-нибудь задумывались, почему каждая программа на C++ начинается с int main(), а не с void main()? И что на самом деле происходит, когда вы пишете return 0? Этот вопрос — настоящий хит на Stack Overflow, собравший тысячи просмотров и сотни комментариев. Казалось бы, элементарная тема, но она скрывает в себе целый пласт тонкостей, которые разделяют C и C++, а также начинающих и опытных разработчиков.

В этой статье мы не просто дадим сухой ответ. Мы проведем сравнение подходов в C и C++, разберем стандарты, покажем реальные примеры кода и расскажем, как правильно работать с возвращаемым значением main(), чтобы ваш код был не только рабочим, но и переносимым. Если вы изучаете C++ или пишете на нём каждый день — эта статья для вас.

Короткий ответ: что должна возвращать main() в C++?

Если вы спешите, вот суть: функция main() в C++ должна возвращать int. Это строгое требование стандарта (начиная с C++98 и до C++23). Возвращаемое значение сообщает операционной системе, успешно ли завершилась программа.

Вот минимальный корректный код:

#include <iostream>

int main() {
    std::cout << "Hello, World!" << std::endl;
    return 0; // Успешное завершение
}

Но это только верхушка айсберга. Давайте копнём глубже.

Почему именно int, а не void? Историческая справка

В самых ранних версиях C (до стандарта ANSI C) тип main() не был строго определён. Многие компиляторы позволяли писать void main(), и это работало. Однако с приходом стандартизации (C89/C90 для C и C++98 для C++) было решено, что main() должна возвращать код завершения операционной системе.

Почему? Потому что скрипты, Makefile'ы и другие программы часто проверяют, как завершился ваш процесс. Код возврата 0 означает «успех», а любое ненулевое значение — «ошибка» (или определённый тип ошибки). Если бы main() была void, вы бы не могли передать эту информацию.

В C++ ситуация ещё строже. Стандарт C++ (раздел [basic.start.main]) прямо говорит: main() должна иметь тип int. Любое другое объявление (например, void main()) — это расширение компилятора и делает код непереносимым.

Сравнение C и C++: в чём разница?

Хотя оба языка требуют int main(), есть несколько ключевых отличий:

  • Неявный return 0 в C++: Если вы не напишете return в конце main(), C++ автоматически вставит return 0. В C (начиная с C99) это тоже работает, но в старых стандартах (C89) отсутствие return приводило к неопределённому поведению.
  • Аргументы командной строки: В C++ вы можете объявить int main(int argc, char* argv[]) или int main(). В C также есть третий вариант с окружением (char* envp[]), но в C++ он не стандартизирован (хотя многие компиляторы поддерживают).
  • void main(): В C некоторые компиляторы (например, для встраиваемых систем) могут разрешать void main(). В C++ это грубая ошибка, и код не скомпилируется в строгом режиме.

Пример для C++ (работает всегда):

int main() {
    std::cout << "C++ автоматически вернёт 0" << std::endl;
    // return 0; // можно не писать
}

Пример для C (требует явного return в старых стандартах):

#include <stdio.h>

int main() {
    printf("В C89 нужно явно возвращать 0\n");
    return 0; // обязательно
}

Что означают коды возврата? Разбор на примерах

Код возврата — это целое число от 0 до 255 (на большинстве систем). 0 — успех, ненулевое значение — ошибка. Вы можете использовать макросы из <cstdlib> для читаемости:

  • EXIT_SUCCESS (обычно 0)
  • EXIT_FAILURE (обычно 1)

Пример с обработкой ошибок:

#include <iostream>
#include <cstdlib>

int main() {
    int error_code = 0;
    // ... какой-то код, который может завершиться ошибкой
    if (/* ошибка */) {
        std::cerr << "Произошла ошибка!" << std::endl;
        return EXIT_FAILURE;
    }
    return EXIT_SUCCESS;
}

Использование EXIT_SUCCESS и EXIT_FAILURE делает код более портируемым, так как числовые значения могут различаться на разных платформах (хотя на практике 0 и 1 — это стандарт).

Типичные ошибки новичков и как их избежать

Ошибка №1: void main(). Это классика. Даже если ваш компилятор (например, старый Borland или Visual Studio с отключенными предупреждениями) это проглотит, такой код не будет работать на других компиляторах. Всегда пишите int main().

Ошибка №2: Забытый return. В C++ это не страшно (компилятор сам подставит 0), но в C (C89) это UB. Лучше всегда явно писать return 0 или return EXIT_SUCCESS.

Ошибка №3: Использование ненулевого кода возврата без причины. Если программа завершилась успешно, всегда возвращайте 0. Ненулевые коды — только для ошибок.

Ошибка №4: Рекурсивный вызов main(). В C++ это запрещено (в отличие от C, где это допускается). Если вы попытаетесь вызвать main() из самой себя, компилятор выдаст ошибку.

Практический пример: программа с аргументами командной строки

Давайте напишем полезную программу, которая принимает аргументы и возвращает код в зависимости от результата:

#include <iostream>
#include <string>
#include <cstdlib>

int main(int argc, char* argv[]) {
    if (argc < 2) {
        std::cerr << "Использование: " << argv[0] << " <им                

Блоги

Рекомендаций по книгам