main 함수
main 함수 (The main function)
프로그램은 호스티드 환경(hosted environment)에서 프로그램의 시작점으로 지정된, main 이라는 전역 함수를 반드시 포함해야 해요. main은 다음 형태 중 하나를 가져야 해요.
int main() { body } (1)
int main(int argc, char* argv[]) { body } (2)
int main(/* implementation-defined */) { body } (3)
- 환경이 제공하는 인자와 독립적으로 실행되는 main 함수.
- 환경이 제공하는 인자를 받는 main 함수.
argc와argv의 이름은 임의로 정할 수 있고 매개변수 타입의 표현도 마음대로예요.int main(int ac, char** av)도 마찬가지로 유효해요. - 구현 정의 타입의 main 함수로
int를 반환해요. C++ 표준은 구현 정의 main 함수가 선택적(추가) 매개변수를argv뒤에 두기를 권장해요.
- argc — 프로그램이 실행되는 환경에서 프로그램에 넘겨진 인자 수를 나타내는 음이 아닌 값.
- argv —
argc + 1개의 포인터 배열의 첫 요소를 가리키는 포인터. 마지막 포인터는 null 이고, 그 앞의 포인터들(있으면)은 실행 환경에서 프로그램에 넘겨진 인자를 나타내는 null 로 끝나는 멀티바이트 문자열들을 가리켜요.argv[0]이 null 포인터가 아니면(또는 동등하게argc > 0이면), 프로그램을 호출하는 데 쓰인 이름을 나타내는 문자열이나 빈 문자열을 가리켜요. - body — main 함수의 본문.
출처: cppreference
본문
설명 (Explanation)
main 함수는 정적 저장 기간의 비지역 객체들이 초기화된 뒤, 프로그램 시작 시 호출돼요. main은 운영 체제가 있는 호스티드 환경에서 실행되는 프로그램의 지정된 진입점이에요. 프리스탠딩(freestanding) 프로그램(부트 로더, OS 커널 등)의 진입점은 구현 정의예요.
두 매개변수 형태의 main 함수 매개변수들은 실행 환경에서 임의의 멀티바이트 문자열(보통 명령줄 인자로 알려진)을 넘길 수 있게 해요. 포인터 [argv[1], argv[argc - 1]]는 이 문자열들 각각의 첫 문자를 가리켜요. argv[0](null 이 아니면)은 프로그램 자체를 호출하는 데 쓰인 이름을 나타내는 null 로 끝나는 멀티바이트 문자열의 첫 문자를 가리키는 포인터예요 (실행 환경이 지원하지 않으면 빈 문자열 ""일 수도 있어요). 이 문자열들은 수정 가능하지만, 이런 수정은 실행 환경으로 다시 전파되지 않아요. 예를 들어 std::strtok에 쓸 수 있죠. argv가 가리키는 배열의 크기는 적어도 argc + 1이고, 마지막 요소 argv[argc]는 null 포인터임이 보장돼요.
main 함수는 몇 가지 특별한 성질이 있어요.
- main 함수의 본문에
return문이 없어도 돼요. 제어 흐름이return문을 만나지 않고 main 의 끝에 도달하면return 0;을 실행한 것과 같은 효과가 있어요. return(또는 main 끝에 도달해 암시적으로 return)의 실행은, 우선 함수를 정상적으로 떠나는 것(자동 저장 기간 객체를 파괴하고 main 의 사후 조건 어서션을 평가하는 것, C++26부터)과 동등하고, 그 다음return의 인자와 같은 인자로std::exit을 호출하는 것과 동등해요 (std::exit는 그다음 정적 객체를 파괴하고 프로그램을 종료해요).
main 함수에는 몇 가지 제약이 있어요 (위반하면 프로그램은 규칙 위반이 돼요).
- 프로그램 어디에서도 이름을 붙일 수 없어요.
- 특히 재귀적으로 호출할 수 없어요.
- 그 주소를 취할 수 없어요.
typeid표현식이나decltype지정자에 쓸 수 없어요 (C++11부터).
- 미리 정의할 수 없고 오버로드할 수 없어요. 사실상 전역 네임스페이스의
main이름은 함수에게 예약돼 있어요 (단 클래스, 네임스페이스, 열거형, 비전역 네임스페이스의 모든 개체에 이름을 붙이는 데는 쓸 수 있어요. 단main이라는 개체는 어떤 네임스페이스에서도 C 언어 링키지로 선언될 수 없어요). "C++"이외의 언어 링키지로 선언될 수 없고,constexpr(C++11부터),consteval(C++20부터),inline,static으로도 선언될 수 없어요.- 삭제된(deleted) 것으로 정의될 수 없어요. (C++11부터)
- 반환 타입을 추론할 수 없어요 (
auto main() {...}는 허용되지 않아요). (C++14부터) - 코루틴이 될 수 없어요.
- 명명된 모듈에 붙을 수 없어요. (C++20부터)
참고 (Notes)
main함수가 함수 try 블록으로 정의되면, 정적 객체의 소멸자가(함축된std::exit에 의해 파괴되면서) 던지는 예외는 그 try 블록이 잡아내지 못해요.- OS 명령줄에서 주어진 인자가
argv가 가리키는 멀티바이트 문자 배열로 변환되는 방식은 구현 정의 처리가 개입할 수 있어요. (Parsing C++ Command-Line Arguments MSDN, Shell Introduction POSIX) - 매우 흔한 구현 정의 형태의 main 함수는
argc,argv외에char**타입의 세 번째 인자를 가지는데, 실행 환경 변수를 가리키는 포인터 배열을 가리켜요.
예제 (Example)
프로그램에게 입력을 어디서 찾고 결과를 어디에 쓸지 알려 주는 방법을 보여 줘요. 가능한 호출 형태는 ./convert table_in.dat table_out.dat.
#include <cstdlib>
#include <iomanip>
#include <iostream>
int main(int argc, char *argv[])
{
std::cout << "argc == " << argc << '\n';
for (int ndx{}; ndx != argc; ++ndx)
std::cout << "argv[" << ndx << "] == " << std::quoted(argv[ndx]) << '\n';
std::cout << "argv[" << argc << "] == "
<< static_cast<void*>(argv[argc]) << '\n';
/* ... */
return argc == 3 ? EXIT_SUCCESS : EXIT_FAILURE; // optional return value
}
가능한 출력:
argc == 3
argv[0] == "./convert"
argv[1] == "table_in.dat"
argv[2] == "table_out.dat"
argv[3] == 0
결함 보고 (Defect reports)
동작 변경 결함 보고로 주요하게 조정된 내용은 이래요. main 의 매개변수 이름을 지나치게 제한하던 것을 모든 유효한 이름을 지원하게 함(CWG 1003), main 이 언어 링키지로 선언되는 것이 금지됨(CWG 1886), main 이 consteval로 선언되는 것이 금지됨(CWG 2479), N3214 이후 main 의 사용 여부가 명확해지고 이름이 붙으면 사용된 것으로 간주됨(CWG 2811), main 이 "C++" 언어 링키지로 선언되는 것이 허용됨(P3618R0) 등이에요.