빌드

Jaemyeong Lee·2024년 8월 9일
0

FastCampusC++

목록 보기
48/78

C++ 빌드 과정에 대한 예제 코드 및 주석 분석

이번 포스트에서는 C++에서의 빌드 과정과 관련된 코드 예제를 한 줄씩 분석하고, 그 의미를 자세히 설명합니다. 이 코드 예제와 주석은 컴파일과 링크 과정에서 발생할 수 있는 문제를 이해하는 데 도움이 됩니다.

1. 기본 코드 분석

#include <iostream>
#include <string>

#define SQUARE(X) X*X

using namespace std;
  • #include <iostream>: 표준 C++ 라이브러리의 iostream 헤더 파일을 포함하여 cout과 같은 입출력 스트림을 사용할 수 있게 합니다.
  • #include <string>: C++ 표준 라이브러리의 string 클래스를 사용하기 위해 포함된 헤더 파일입니다.
  • #define SQUARE(X) X*X: 전처리기 매크로로, SQUARE(X)는 텍스트 대체되어 X*X로 변환됩니다. 주의해야 할 점은 매크로는 단순 텍스트 치환이므로, 의도하지 않은 부작용이 발생할 수 있습니다.
  • using namespace std;: std 네임스페이스에 있는 이름을 전역적으로 사용 가능하게 합니다. 즉, std::cout 대신 cout을 사용할 수 있게 합니다.
int sum(int, int);
  • int sum(int, int);: sum 함수의 프로토타입을 선언합니다. 이 함수는 두 개의 int 값을 받아서 합을 반환할 것입니다. 그러나 실제 구현은 이 코드에 포함되어 있지 않으며, 다른 파일에 있을 것입니다(util.cpp).
int main(int argc, char* argv[])
{
    SQUARE(1);
  • int main(int argc, char* argv[]): 프로그램의 시작 지점인 main 함수입니다. argc는 명령줄 인수의 개수를 나타내며, argv는 명령줄 인수를 문자열 배열로 전달합니다.
  • SQUARE(1);: 이 코드는 전처리 단계에서 1*1으로 대체됩니다. 그러나 실제로는 결과가 사용되지 않기 때문에 이 줄은 아무런 효과가 없습니다.
    int total = 0;
    for (int i = 0; i < argc; ++i)
    {
        string arg(argv[i]);
        int num = stoi(arg);
        total = sum(total, num);
    }
    cout << total << endl;
}
  • int total = 0;: 합계를 저장할 변수를 선언하고 0으로 초기화합니다.
  • for (int i = 0; i < argc; ++i): argc에 저장된 인수의 수만큼 반복문을 실행합니다.
  • string arg(argv[i]);: argv[i]에 저장된 문자열을 string 객체로 변환합니다.
  • int num = stoi(arg);: 문자열 arg를 정수로 변환합니다.
  • total = sum(total, num);: sum 함수를 호출하여 totalnum의 합을 계산하고 total에 저장합니다.
  • cout << total << endl;: 최종 합계를 출력합니다.

2. 주석 분석: 빌드 및 컴파일 과정

// 1. 시작
// 2. Developer 입력
// 3. Developer Command Prompt for VS 2019 선택
// 4. cd 를 이용하여 main.cpp 파일의 경로로 이동
  • 설명: Visual Studio에서 개발자 명령 프롬프트를 실행하여 main.cpp 파일이 있는 디렉토리로 이동하는 과정입니다. 이 명령 프롬프트는 컴파일러와 링커를 실행할 수 있는 환경을 제공합니다.
// 컴파일 후 실행
// 1. cl main.cpp util.cpp
// 2. main.exe 10 20 30
// 3. del *.obj
// 4. del main.exe
  • cl main.cpp util.cpp: cl 명령은 C++ 컴파일러를 실행합니다. 이 명령은 main.cpputil.cpp를 컴파일하고, 링커를 통해 main.exe 실행 파일을 생성합니다.
  • main.exe 10 20 30: 생성된 main.exe 파일을 실행하고, 명령줄 인수로 10, 20, 30을 전달합니다. 이 값들이 argv로 전달되어 sum 함수에서 계산됩니다.
  • del *.obj: 중간 컴파일 결과물인 .obj 파일들을 삭제합니다.
  • del main.exe: 생성된 실행 파일 main.exe를 삭제합니다.
// 1. cl main.cpp
// 안 됨, sum 함수를 찾을 수 없음, obj 파일은 생성 됨
  • 설명: main.cpp만 컴파일하면 sum 함수가 구현된 util.cpp가 없기 때문에 링크 단계에서 sum 함수가 정의되지 않아 에러가 발생합니다. 하지만 main.obj 파일은 생성됩니다.
// 1. cl util.cpp
// 안 됨, main 함수를 찾을 수 없음, obj 파일은 생성 됨
  • 설명: util.cpp만 컴파일하면 main 함수가 정의되지 않아 main을 찾을 수 없다는 오류가 발생합니다. 그러나 util.obj 파일은 생성됩니다.
// 1. cl main.cpp util.cpp /c
// main.obj, util.obj 파일이 생성 되어있음. /c는 컴파일만 하겠다는 의미
// 2. link main.obj util.obj
// main.exe 생성
  • cl main.cpp util.cpp /c: 이 명령은 main.cpputil.cpp를 컴파일하지만, 링크 과정을 수행하지 않고 .obj 파일만 생성합니다. /c 옵션은 컴파일만 하고 링킹은 하지 않겠다는 의미입니다.
  • link main.obj util.obj: 이 명령은 이전에 생성된 .obj 파일들을 링크하여 main.exe 실행 파일을 생성합니다.
// obj가 생성되었다는 것은 컴파일이 되었다는 것을 의미
// 컴파일 후 링킹 과정이 있는데 main.cpp, util.cpp를 각각 별도로 컴파일 하면 링킹에서 실패
  • 설명: .obj 파일이 생성되었다는 것은 컴파일이 성공했다는 의미입니다. 하지만 링킹 과정에서 모든 필요한 함수들이 정의되어 있지 않다면, 링크 오류가 발생할 수 있습니다.
// 1. link main.obj 
// sum 함수를 찾을 수 없음
  • 설명: main.obj만 링크하려고 하면, sum 함수의 정의를 포함하고 있는 util.obj 파일이 없기 때문에 링크 오류가 발생합니다.
// 1. cl main.cpp /P
// main.i 생성, 전처리만 함
// iostream 파일들이 main.cpp 에 붙여넣은 결과가 생성
// SQUARE와 같이 전처리 매크로도 대체가 됨
  • cl main.cpp /P: /P 옵션은 컴파일러가 전처리 단계만 수행하도록 하며, 결과물을 .i 파일로 출력합니다. 이 파일에는 모든 #include된 파일의 내용이 포함되며, 매크로 치환도 완료된 상태입니다.
  • main.i 생성: 전처리된 파일이 생성됩니다. 이 파일은 실제로 컴파일되지 않으며, 전처리 결과만을 보여줍니다.

요약

  1. 컴파일 단계:

    • 소스 파일(.cpp)이 컴파일되어 중간 산출물(.obj)이 생성됩니다. 이 단계에서는 함수 프로토타입이나 변수 선언의 문법 오류를 확인합니다.
    • 전처리 단계에서 #include 파일이 포함되고, 매크로는 텍스트 치환으로 처리됩니다.
  2. 링크 단계:

    • 각각의 .obj 파일들을 하나로 결합하여 실행 가능한 프로그램(.exe)을 생성합니다.
    • 함수나 변수가 정의되지 않았거나, 선언만 되어 있고 구현이 없는 경우 링크 오류가 발생할 수 있습니다.
  3. 빌드 과정:

    • 모든 소스 파일을 한꺼번에 컴파일하고 링크하는 방법과, 각각의 파일을 별도로 컴파일한 후 링크하는 방법이 있습니다.
    • 후자의 경우, 컴파일된 .obj 파일들을 정확히 링크해야 실행 파일이 제대로 생성됩니다.
  4. 전처리:

    • 전처리된 파일을 확인하여, 매크로 치환이 어떻게 이루어졌는지, #include 파일들이 어떻게 포함되었는지 확인할 수 있습니다.
profile
李家네_공부방

0개의 댓글