Функция main в C++: формы записи, аргументы и возвращаемое значение

Функция main в C++: формы записи, аргументы и возвращаемое значение Полезное

main — это функция, с которой начинается выполнение любой обычной программы на C++: операционная система передает управление именно в нее, а не в первую строку файла. Возвращаемый тип у нее всегда int, и по этому числу среда узнает, успешно ли завершилась программа.

Ниже разберем, зачем нужна main, две ее стандартные формы записи, как через нее принять аргументы командной строки (argc и argv), что и зачем она возвращает, а также частые ошибки вроде void main(). Все примеры прогнаны компилятором, вывод в статье — реальный.

Что такое main и зачем она нужна

Когда вы запускаете скомпилированную программу, стартовый код рантайма готовит окружение и вызывает вашу main. Поэтому ровно одна main должна быть в программе: без нее компоновщик (линкер) выдаст ошибку и исполняемый файл не соберется.

Внутри main находится точка входа в вашу логику: отсюда вы вызываете другие функции, создаете объекты, читаете ввод. Когда main завершается, программа заканчивает работу и возвращает коду операционной системы число — признак успеха или ошибки.

У main есть ограничения, которых нет у обычных функций. Ее нельзя перегрузить, нельзя объявить inline, static или constexpr, и ее нельзя вызывать из самой программы, в том числе рекурсивно. Это единственная функция, точку входа в которую выбирает не программист, а среда исполнения.

Минимальный рабочий пример

Начнем с самой короткой полноценной программы. Ее можно скопировать в файл, скомпилировать и запустить:

#include <iostream>

int main() {
    std::cout << "Hello, World!" << std::endl;
    return 0;
}

Вывод программы:

Hello, World!

Разберем по строкам:

  1. #include <iostream> подключает заголовочный файл стандартной библиотеки ввода-вывода — без него не будет std::cout.
  2. int main() — объявление точки входа: тип возврата int, имя main, пустой список параметров.
  3. Фигурные скобки { } ограничивают тело функции: открывающая — начало, закрывающая — конец.
  4. std::cout << "Hello, World!" выводит строку в консоль; std::endl добавляет перевод строки и сбрасывает буфер.
  5. return 0; завершает программу с кодом 0 — признаком успешного выполнения.

Здесь std:: — это префикс пространства имен std, в котором лежат cout, endl и остальные средства стандартной библиотеки. Пространства имен нужны, чтобы имена из библиотеки не конфликтовали с вашими.

Две стандартные формы записи main

Стандарт C++ гарантирует поддержку ровно двух форм точки входа. Выбор между ними зависит от одного: нужны программе аргументы командной строки или нет.

Форма записи Когда выбирать
int main() программе не нужны аргументы командной строки
int main(int argc, char* argv[]) программа читает аргументы, переданные при запуске

Обе формы равноправны, и обе обязаны поддерживаться в любой размещенной (hosted) среде. Параметры второй формы значат следующее:

  • argc (argument count) — число переданных аргументов, всегда не меньше 1.
  • argv (argument vector) — массив строк с самими аргументами; argv[0] — имя или путь запуска программы, а последний элемент argv[argc] равен нулевому указателю.

Проверим это на программе, которая печатает все аргументы:

#include <iostream>

int main(int argc, char* argv[]) {
    std::cout << "argc = " << argc << "\n";
    for (int i = 0; i < argc; ++i) {
        std::cout << "argv[" << i << "] = " << argv[i] << "\n";
    }
    return 0;
}

Если запустить ее вообще без аргументов, argc равен 1, а единственный элемент argv[0] — путь, по которому стартовала программа:

argc = 1
argv[0] = /tmp/.../a.out

Путь у вас будет свой — это и есть argv[0]. Запустите ту же программу командой ./a.out one two, и вывод изменится: argc станет 3, argv[1] будет one, а argv[2] — two. Каждое слово после имени программы, разделенное пробелом, становится отдельным элементом argv.

Встречается и запись char** argv вместо char* argv[] — это то же самое: массив указателей на строки. Некоторые компиляторы разрешают и третий параметр (окружение), но он нестандартен, полагаться на него не стоит.

Что возвращает main

Тип int перед main — это не формальность: возвращаемое число получает операционная система или скрипт, запустивший программу. По соглашению 0 означает успех, любое ненулевое значение — ошибку. Это позволяет, например, в shell-скрипте проверить, отработала ли программа.

Чтобы не запоминать числа, в заголовке <cstdlib> есть две именованные константы — EXIT_SUCCESS и EXIT_FAILURE:

#include <iostream>
#include <cstdlib>

int main() {
    std::cout << "EXIT_SUCCESS = " << EXIT_SUCCESS << "\n";
    std::cout << "EXIT_FAILURE = " << EXIT_FAILURE << "\n";
    // конец main без return: стандарт трактует это как return 0
}

Вывод программы:

EXIT_SUCCESS = 0
EXIT_FAILURE = 1

Обратите внимание: в этом примере нет строки return. У main есть особое правило — если выполнение доходит до закрывающей скобки без return, компилятор подставляет return 0; автоматически. Это работает только для main; в любой другой функции с типом int пропуск return приведет к неопределенному поведению.

Частые ошибки

Самая распространенная неверная запись — void main(). Ее иногда можно встретить в старых учебниках, но стандарт C++ ее не допускает:

#include <iostream>

void main() {
    std::cout << "bad" << std::endl;
}

На современном компиляторе это не предупреждение, а ошибка компиляции — программа не соберется:

error: 'main' must return 'int'

Исправление простое — вернуть корректный тип и, при желании, явный код возврата:

#include <iostream>

int main() {
    std::cout << "ok" << std::endl;
    return 0;
}

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

Выводы

  • main — точка входа программы на C++: с нее операционная система начинает выполнение, и она должна быть в программе ровно одна.
  • Возвращаемый тип всегда int; 0 (или EXIT_SUCCESS) означает успешное завершение, ненулевое значение — ошибку.
  • Стандарт гарантирует две формы: int main() без аргументов и int main(int argc, char* argv[]) для чтения командной строки, где argc — число аргументов, argv — массив строк.
  • Если в main дойти до конца без return, компилятор сам подставит return 0 — но только для main, не для других функций.
  • void main() не соответствует стандарту; на строгих компиляторах это ошибка сборки. Также main нельзя перегружать, вызывать рекурсивно и объявлять inline, static или constexpr.

Где применяется и что учить дальше

Правильно оформленная main — первое, с чего начинается любой проект на C++: от учебной консольной программы до утилиты, которая разбирает аргументы командной строки и возвращает осмысленный код завершения в CI-пайплайн. Понимание argc/argv и кодов возврата нужно, как только программа перестает быть одним Hello, World и начинает взаимодействовать с окружением.

Освойте тему на практике

Если хочется освоить C++ системно — от синтаксиса и точки входа до работы с памятью и стандартной библиотекой — посмотрите курс C++ Basic. Оценить формат и уровень до старта помогают бесплатные открытые уроки Otus — живые занятия с преподавателями.

Смежные темы: Функция main в семействе языков C.

FAQ

Можно ли писать int main(void) в C++, как в C? Да, это допустимо и означает то же самое, что int main() — функция без параметров. В C++ пустые скобки уже значат «без аргументов», поэтому void внутри избыточен, но ошибкой не является.

Почему в примерах иногда нет return 0, и программа все равно работает? Потому что для main язык делает исключение: при достижении конца функции без return подставляется return 0. Для наглядности и переносимости кода return 0; все же лучше писать явно.

Обязательно ли main должна быть в глобальном пространстве имен? Да. main должна быть свободной функцией в глобальной области; ее нельзя сделать методом класса или поместить в свое пространство имен — среда исполнения ищет ее именно как глобальную main.

OTUS Журнал
Скидка 5% 14-20 сентября на курсы (popup)