Avatar ·

Что должна возвращать функция main() в C++: void, int или что-то ещё?

Всем привет! Я начал изучать C++ недавно, и у меня возникла путаница с функцией `main()`. В разных источниках я видел разные объявления: где-то пишут `int main()`, где-то `void main()`, а иногда даже `main()` без указания типа. Я попробовал написать простую программу: ```cpp #include using namespace std; void main() { cout << "Hello, world!" << endl; } ``` В Visual Studio это скомпилировалось и даже работало, но на другом компиляторе (g++) выдало ошибку: `'::main' must return 'int'`. Почему так? Что на самом деле должна возвращать `main()`? И нужно ли что-то возвращать в конце, если я пишу `int main()`? Будет ли это работать, если я ничего не напишу в `return`? И ещё вопрос: а что именно возвращает `main()` и кому это нужно? Объясните, пожалуйста, для новичка, как правильно писать точку входа в программу на C++. <<>>

Правильный ответ: main() всегда должна возвращать int

В стандарте C++ (и C) чётко сказано: функция main() должна иметь тип возврата int. Это единственный стандартный и переносимый вариант. Использование void main() — это грубая ошибка, которая может работать в некоторых старых или нестандартных компиляторах (например, в некоторых версиях Visual Studio), но не является переносимой и нарушает стандарт.

// Правильно:
int main() {
    // код
    return 0;
}

Почему именно int?

Возвращаемое значение main() передаётся операционной системе (или вызывающей среде). Оно называется кодом возврата или статусом выхода. По соглашению:

  • 0 или EXIT_SUCCESS — программа завершилась успешно.
  • 1 или EXIT_FAILURE — программа завершилась с ошибкой.

Это значение могут использовать скрипты, командная строка или другие программы, чтобы узнать, как завершилась ваша программа. Например, в bash:

./myprogram
if [ $? -eq 0 ]; then
    echo "Всё хорошо"
else
    echo "Ошибка"
fi

Можно ли не писать return 0?

Да, в C++ (но не в C!) есть специальное правило: если в main() нет оператора return, то компилятор автоматически вставляет return 0; в конец. Это работает только для main() — для других функций такое недопустимо. Однако для ясности кода рекомендуется всегда явно писать return 0; или return EXIT_SUCCESS;.

// Тоже правильно (но лучше явно):
int main() {
    std::cout << "Hello\n";
    // Неявно return 0;
}

Другие разрешённые формы main()

Стандарт C++ допускает две формы точки входа:

  • int main() — без аргументов командной строки.
  • int main(int argc, char* argv[]) — с аргументами командной строки.

Также некоторые компиляторы поддерживают int main(int argc, char* argv[], char* envp[]) (с переменными окружения), но это уже расширение, не входящее в стандарт.

int main(int argc, char* argv[]) {
    std::cout << "Программа: " << argv[0] << "\n";
    std::cout << "Аргументов: " << argc - 1 << "\n";
    return 0;
}

Что насчёт void main()?

Никогда не используйте void main(). Это нестандартная конструкция, которая:

  • Не компилируется на многих компиляторах (g++, clang, MSVC в режиме строгого соответствия).
  • Не возвращает статус операционной системе, что может привести к неопределённому поведению.
  • Может работать только в старых версиях некоторых компиляторов (например, Turbo C++ или MSVC с отключёнными предупреждениями).

Если вы видите void main() в учебнике — скорее всего, этот учебник устарел или написан для C (где тоже такое недопустимо со стандарта C99).

Итог

Всегда пишите int main(). В конце явно возвращайте 0 при успехе или код ошибки при неудаче. Это гарантирует переносимость, правильную работу с операционной системой и соответствие стандарту C++.

<<>>

Дополнение: использование EXIT_SUCCESS и EXIT_FAILURE

Вместо магических чисел 0 и 1 лучше использовать константы из заголовочного файла <cstdlib> (или <stdlib.h> в C):

#include <iostream>
#include <cstdlib>  // для EXIT_SUCCESS и EXIT_FAILURE

int main() {
    if (/* условие успеха */) {
        std::cout << "Программа выполнена успешно\n";
        return EXIT_SUCCESS;  // обычно 0
    } else {
        std::cerr << "Произошла ошибка\n";
        return EXIT_FAILURE;  // обычно 1
    }
}

Преимущество: код становится самодокументируемым и переносимым. В разных ОС значения EXIT_SUCCESS и EXIT_FAILURE могут отличаться от 0 и 1 (хотя на практике почти всегда совпадают).

Также можно использовать std::exit() для завершения программы из любой функции, но это более грубый способ — не вызываются деструкторы локальных объектов (в отличие от return из main()).

И помните: если ваша программа никогда не должна завершаться с ошибкой, всё равно пишите return 0; в конце — это хороший тон и привычка, которая убережёт вас от неожиданностей при переносе кода на другой компилятор.