본문 바로가기
<CPP>/BASIC

0. Main 함수

by CodeGrimie 2021. 1. 7.
main()
{

}

C와 CPP Main 함수의 문법상의 차이점

CPP가 원래 ' C with Classes ' 란 이름이었던 만큼 Main 함수의 구조는 C와 큰 차이가 없다.

 

CPP Main 함수의 기본적인 형태(표준)

/*
* CPP STANDARD MAIN FUNCTION
*/

#define	HAS_ARGUMENT	1

#if	HAS_ARGUMENT

int main()
{
	return 0;
}

#else

// int main(int argc, char *argv[])
int main(int argc, char **argv)
{
	return 0;
}

#endif

만약 C 표준을 지켜 프로그래밍을 해왔다면 한 가지 차이점이 눈에 띌 것이다.

 

표준 코드의 관점에서 CPP에서는 C와 달리 Main 함수에 인자가 없을 때 비워둬도 된다.

이는 CPP가 C를 대체하기 위해서 만들어진 만큼 CPP의 컴파일러가 좀 더 엄격하게 문법을 따지도록 설계되었기 때문이다.

좀 더 명확히 이해하기 위해서 아래의 C 코드를 살펴보자.

 

C의 느슨한 체크

void withVoid(void)	{}
void withOutVoid()	{}

int main(void)
{
	withVoid(1);	// ERROR
	withOutVoid(1);	// WARNING or OK
    
	return 0;
}

코드에서도 확인할 수 있듯이 C 문법에서는 함수의 인자 여부와 관계없이 함수를 호출할 때 인자를 넣어줄 수 있다.

그래서 C 표준에서 인자가 없는 함수의 경우엔 반드시 void를 명시해 컴파일러가 에러를 발생시키도록 명시하고 있다.

 

다행히도 최근의 컴파일러들은 이러한 문제에 대해서 경고를 해주지만 어디까지나 경고일 뿐 에러는 아니다.

경고 단계를 낮추면 C의 문법과 표준에 따라 문제없이 컴파일이 된다.

Main 함수는 CPP 프로그램의 처음이자 끝을 뜻한다.

어떤 언어로 게임을 만들 던 간에 내부적으로는 언제나 절차대로 작동한다.

우리가 CPP로 객체 지향적으로 코드를 작성하더라도 컴파일을 거치고 나면 결국엔 절차 지향으로 구조화된다.

이는 프로그램(Program)이란 단어에 그 이유가 있다.

 

프로그램은 Pro-(앞서서, 미리)와 Gram(그리다, 작성하다)의 합성 단어다.

의외로 단어 자체는 고대 그리스 시대부터 사용되어온 오래된 역사를 가졌다.

한국어로 직역하면 ' 미리 작성하다 '로 해석되는데, 요즘 말로는 ' To Do List(할 일 목록) '으로 대입할 수 있다.

실제로 고대 그리스 시대에서는 ' 공지사항 '의 개념으로 사용했다고 한다.

 

그래서 컴퓨터 역시 ' 연산해야 할 일 목록'을 미리 작성해둔 것을 프로그램이라고 부른다.

대부분의 경우 단지 목록을 적는 언어(어셈블리, C/C++, 자바, 파이썬..)가 달라지는 것뿐이다.

 

컴퓨터는 구조상 절차적으로 연산할 수밖에 없다.

그래서 컴파일러를 거쳐서 컴퓨터에게 전해지는 ' 연산해야 할 일 목록 '은 언제나 절차적으로 잘 정리돼서 전해진다.

그러기 위해서는 언제 프로그램이 시작되고 끝나는지를 명확하게 알 수 있어야 하고 이게 바로 Main 함수의 존재 이유다.

 

명확하게 이해하기 위해서 아래의 코드를 살펴보자.

 

CPP 코드의 컴파일 초간단 예시

#define	IS_UNZIP	0

#if	IS_UNZIP
/* CODE PROGRAMMER CODE */

void makeThree()
{
    int a, b, result;
    a = 1;
    b = 2;
    result = a + b;
}

int main()
{  
	makeThree();
    
	return 0;
}

#else
/* CODE COMPILER CLEAN UP */

int main()
{
    {
        int a, b, result;
        a = 1;
        b = 2;
        result = a + b;
    }
    
	return 0;
}

#endif

대부분의 경우 CPP 프로그램은 Main 함수 내에서 모든 것이 이루어진다.

위의 코드와 같이 함수를 사용한다 하더라도 컴파일하는 과정에서는 해당 함수의 코드를 가져와서 복붙 하는 것과 비슷하다.

(물론 컴파일러는 훨씬 복잡한 일을 한다. 이것은 어디까지나 예시일 뿐이다.)

이 과정에서 객체지향적으로 작성된 CPP 코드는 C에 비해서 컴파일 속도가 더 걸리기도 한다.

 

결과적으로는 하나의 프로그램에서 사용되는 CPP의 코드는 언제나 Main 함수 안에 존재한다.

return 0;는 프로그램이 문제없이 종료되었다는 것을 의미한다.

CPP 표준에서는 왜 Main 함수에 항상 return 0;가 들어가는 걸까?

곧이 곧대로 해석을 하면 Main함수가 종료될 때 0을 반환했다는 것을 알 수 있다.

다르게 말하면 0을 반환하면 프로그램이 정상적으로 종료되었다는 뜻으로 해석할 수 있다.

 

좀 더 이유를 명확히 알기 위해 C의 Main 함수 발전 역사를 살펴보자.

 

▼ 탄생 초창기 C의 Main 함수 모습

main()
{
	// CODE
}

탄생 초창기 C의 Main 함수의 형태는 단순했다.

프로그램의 크기도 크지 않았고 프로그램들끼리 연동도 별로 없었다.

 

▼ C99표준 C의 Main 함수 모습

int main(void)
{
    return 0;
}

그러나 컴퓨터의 발전과 더불어 대중적인 윈도우 운영체제의 등장으로 프로그램 개발의 흐름이 크게 바뀌었다.

프로그램들이 서로 유동적이거나 영향을 끼치게 되었다.

 

가령 윈도우에서 정말 멋진 최신 게임을 개발하면서 테스트 플레이한다고 가정해보자.

신나게 게임을 즐기고 있다 갑자기 게임이 터져버린 상황이 발생했다.

프로그래머는 이 치명적인 버그를 고치기 위해서 어떤 부분이 문제였는지 확인해야만 한다.

문제는 게임을 개발하는데 사용되는 코드의 양은 프로그래머의 생각보다 훨씬 많았고 어떤 부분에서 문제가 발생했는지 찾기 쉽지 않았다는 것이다.

이때 이 return이 큰 도움이 될 것이다.

 

프로그래머는 애초에 코드를 작성하는 단계에서 에러를 검출하는 코드를 작성한다.

여러가지 문제가 발생할 수 있는 경우를 상정하고 해당하는 문제가 발생한 경우에 따라 return 값을 지정하는 것이다.

아주 간단한 코드 예시를 살펴보자.

 

▼ CPP에서 return을 이용한 에러 코드

int main()
{
    int a;
    a = 3;
    
    if (a < 10)
        return -1; // Something Wrong
    
    return 0;
}

a가 10보다 작을 때 0이 아닌 -1을 반환하도록 설정했다.

컴파일 해서 실행하면 실행결과가 -1이 반환했다고 알려주는데 이러한 원리를 이용해서 특정 에러코드를 포함한 팝업창을 띄어 문제가 발생한 위치를 확인 할 수 있다.

 

표준은 아니지만 개인적으로는 return 반환값에 소괄호를 씌어주는 것을 선호한다.

좀 더 명확하게 반환값을 인지할 수 있기 때문이다.

 

▼ 반환값을 소괄호 씌운 코드

int main()
{
	return (0);
}

'<CPP> > BASIC' 카테고리의 다른 글

5. 정수  (0) 2021.01.08
4. 출력문  (0) 2021.01.08
3. 주석(Comment)  (0) 2021.01.08
2. 문장부호  (0) 2021.01.08
1. 괄호(Bracket)  (2) 2021.01.08

댓글