(VS C/C++)C언어 실행 파일 작성에서 main함수의 역할

visual studio c/c++, gcc,c++ C/C++언어

프로그램 언어마다 프로그램의 시작 부분이 다릅니다. C언어에서는 main 함수가 프로그램의 시작을 가리킵니다. 이 글에서는 C언어 프로그램의 시작 함수 코딩 방법과 main 함수가 없을 경우 복수개 존재할 경우의 에러 메시지에 대해서 소개합니다. 참고로 이 글의 샘플은 Microsoft Visual Studio Community 2022 (64-bit)에서 작성되었습니다.

main 함수 기본 구성

main 함수의 기본 구성은 다음과 같습니다. VS프로젝트 samplec에 sample.c 파일로 저장합니다. 빌드(컴파일 + 링크)를 하고 실행 파일 samplec.exe를 생성합니다.

#include <stdio.h>

int main(int argc, char* argv[]) {
	printf("argc=%d\n", argc);
	for (int i = 0; i < argc; i++)
	{
		printf("argv[%d]=%s\n",i, argv[i]);
	}
	return 9;
}
  • main 함수 앞에 지정하는 int 는 리턴 값의 타입입니다. 리턴 값이 필요 없는 프로그램을 만들 경우에는 void를 지정합니다. 위 코드에서는 0를 리턴했습니다.
  • int argc 에는 실행 파일(samplec.exe)을 포함한 인수의 갯수가 설정됩니다.
  • char* argv[] 배열에는 실행 파일(samplec.exe)을 포함한 인수의 정보가 설정됩니다.

실행 결과는 다음과 같습니다.

C:\Temp\samplec\x64\Debug>samplec.exe a1 a2 a3
argc=4
argv[0]=samplec.exe
argv[1]=a1
argv[2]=a2
argv[4]=a3
C:\Temp\samplec\x64\Debug>echo %errorlevel%
9

argc에는 samplec.exe를 가지고 있는 인수 a0을 포함해서 인수 a1, a2, a3의 총 갯수 4가 설정되었습니다. 그리고 argv 배열에는 samplec.exe, a1, a2, a3의 명령과 인수가 순서대로 설정되어 있습니다.

우리가 지금까지 무심코 사용했던 ipconfig.exe 또는 xcopy.exe와같은 프로그램도 위의 main 함수의 기본 구성으로 만들어졌습니다. ipconfig /? 를 실행하면 도움말이 표시되는 것과 같이 samplec.exe인수에 /? 문자가 존재하면 도움말을 표시하도록 main 함수의 int argc, char* argv[]를 이용하여 코딩할 수도 있습니다.

main 함수가 없는 경우

다음과 같이 함수 이름 main을 start로 변경해서 컴파일 해 봅니다.

#include <stdio.h>
int start(int argc, char* argv[]) {
	printf("argc=%d\n", argc);
	for (int i = 0; i < argc; i++)
	{
		printf("argv[%d]=%s\n",i, argv[i]);
	}
	return 9;
}

exe 실행 파일의 빌드 과정은 컴파일 + 링크입니다. 다음과 같이 sample.c의 컴파일은 성공해서 sample.obj가 생성 되었습니다만 다음 과정의 링크에서 main을 참조할 수 없어 에러가 발생했습니다.

C:\Temp\samplec\x64\Debug>dir /b
sample.obj
samplec.exe.recipe
samplec.log
samplec.pdb
samplec.tlog
samplec.vcxproj.FileListAbsolute.txt
vc143.idb
vc143.pdb
빌드 시작...
1>------ 빌드 시작: 프로젝트: samplec, 구성: Debug x64 ------
1>sample.c
1>MSVCRTD.lib(exe_main.obj) : error LNK2019: main"int __cdecl invoke_main(void)" (?invoke_main@@YAHXZ) 함수에서 참조되는 확인할 수 없는 외부 기호
1>C:\Temp\samplec\x64\Debug\samplec.exe : fatal error LNK1120: 1개의 확인할 수 없는 외부 참조입니다.
1>"samplec.vcxproj" 프로젝트를 빌드했습니다. - 실패
========== 빌드: 성공 0, 실패 1, 최신 0, 생략 0 ==========

main 함수가 2개 이상 존재하는 경우

main 함수와 상관 없이 하나의 실행 파일 생성하는 프로젝트 내에서는 같은 이름의 함수를 2개 이상 지정할 수 없습니다. 다음 예시는 int test(void)void test(void) 함수가 같은 빌드 단위에 존재할 경우 다음과 같은 에러가 발행합니다.

sample.c

#include <stdio.h>
int main(int argc, char* argv[]) {
	printf("argc=%d\n", argc);
	for (int i = 0; i < argc; i++)
	{
		printf("argv[%d]=%s\n", i, argv[i]);
	}
	return 9;
}
int test(void) {
	printf("Hello World");
	return 0;
}

test.c

#include <stdio.h>
void test(void) { 
	printf("Hello World"); 
}
다시 빌드 시작...
1>------ 모두 다시 빌드 시작: 프로젝트: samplec, 구성: Debug x64 ------
1>sample.c
1>test.c
1>코드를 생성하고 있습니다...
1>test.obj : error LNK2005: test이(가) sample.obj에 이미 정의되어 있습니다.
1>C:\Temp\samplec\x64\Debug\samplec.exe : fatal error LNK1169: 여러 번 정의된 기호가 있습니다.
1>"samplec.vcxproj" 프로젝트를 빌드했습니다. - 실패
========== 모두 다시 빌드: 성공 0, 실패 1, 생략 0 ==========

다음은 main 함수가 중복해서 존재하는 경우의 빌드 결과 입니다.

sample.c

#include <stdio.h>
int main(int argc, char* argv[]) {
	printf("argc=%d\n", argc);
	for (int i = 0; i < argc; i++)
	{
		printf("argv[%d]=%s\n", i, argv[i]);
	}
	return 9;
}
int test(void) {
	printf("Hello World");
	return 0;
}

test.c

#include <stdio.h>
void main(void) { 
	printf("Hello World"); 
}
다시 빌드 시작...
1>------ 모두 다시 빌드 시작: 프로젝트: samplec, 구성: Debug x64 ------
1>sample.c
1>test.c
1>코드를 생성하고 있습니다...
1>test.obj : error LNK2005: main이(가) sample.obj에 이미 정의되어 있습니다.
1>C:\Temp\samplec\x64\Debug\samplec.exe : fatal error LNK1169: 여러 번 정의된 기호가 있습니다.
1>"samplec.vcxproj" 프로젝트를 빌드했습니다. - 실패
========== 모두 다시 빌드: 성공 0, 실패 1, 생략 0 ==========
제목과 URL을 복사했습니다