프로그램 언어마다 프로그램의 시작 부분이 다릅니다. 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의 명령과 인수가 순서대로 설정되어 있습니다.
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 ==========