>  기사  >  백엔드 개발  >  C 언어로 소스 파일을 컴파일하면 어떤 파일이 생성되나요?

C 언어로 소스 파일을 컴파일하면 어떤 파일이 생성되나요?

青灯夜游
青灯夜游원래의
2022-11-23 19:44:5812530검색

C 언어는 ".OBJ" 바이너리 파일(객체 파일)을 생성하기 위해 컴파일됩니다. C 언어에서는 소스 프로그램(.c 파일)이 컴파일러에 의해 컴파일된 후 ".OBJ"라는 접미사가 붙은 바이너리 파일(오브젝트 파일이라고 함)이 최종적으로 생성되며 이를 "링크"라고 합니다. 이 ".OBJ" 파일을 C 언어에서 제공하는 다양한 라이브러리 함수와 연결하여 접미사가 ".EXE"인 실행 파일을 생성합니다.

C 언어로 소스 파일을 컴파일하면 어떤 파일이 생성되나요?

이 튜토리얼의 운영 환경: Windows 7 시스템, c99 버전, Dell G3 컴퓨터.

C 언어 소스 파일 편집

C 언어 소스 파일의 접미사 이름은 ".c", 컴파일된 파일의 접미사 이름은 ".obj", 연결된 실행 파일의 접미사 이름은 " ".exe".

C 언어로 프로그램을 만드는 단계:

  • 편집: C 프로그램의 소스 코드를 만들고 수정하는 것입니다. 우리가 작성하는 프로그램을 소스 코드라고 합니다.

  • 컴파일: 소스코드를 기계어로 변환하는 것입니다. 컴파일러의 출력은 객체 코드가 되고 이를 저장하는 파일을 객체 파일이라고 합니다. 확장자는 .o 또는 .obj입니다. (이 부분의 컴파일은 어셈블리 언어를 컴파일하는 어셈블러 또는 고급 언어를 컴파일하는 컴파일러를 의미합니다.)

  • 링크: 링커는 소스 코드를 컴파일러가 생성한 다양한 모듈에 결합한 후, 제공하는 라이브러리에서 추가합니다. C 언어에 필요한 코드 모듈을 만들고 이를 실행 파일로 결합합니다. 확장자는 Windows에서는 .exe이고 Unix에서는 확장자가 없습니다.

  • 실행: 프로그램을 실행합니다.

C언어 소스 프로그램이 C언어 컴파일러로 컴파일되면 ".OBJ"라는 접미사가 붙은 바이너리 파일(오브젝트 파일이라고 함)이 생성되고, 마지막으로 "Link"라는 소프트웨어가 사용됩니다. ".EXE"라는 접미사가 붙은 실행 파일을 생성하기 위해 C 언어에서 제공하는 다양한 라이브러리 함수가 포함된 ".OBJ" 파일입니다. 분명히 C 언어는 즉시 실행될 수 없습니다.

프로세스 다이어그램은 다음과 같습니다.

C 언어로 소스 파일을 컴파일하면 어떤 파일이 생성되나요?

그림에서 볼 수 있듯이 전체 코드의 컴파일 프로세스는 컴파일과 링크의 두 가지 프로세스로 구분됩니다. 나머지는 연결 과정입니다.

컴파일 프로세스

  • 컴파일 프로세스는 컴파일어셈블리의 두 단계로 나눌 수 있습니다.

Compilation: 컴파일은 소스 프로그램(문자 스트림)을 읽고 이를 어휘적, 문법적으로 분석하고 고급 언어 명령어를 기능적으로 동등한 어셈블리 코드로 변환하는 것입니다. 단계:

첫 번째 단계는 정식 편집 단계 이전에 진행되는 전처리 단계입니다. 전처리 단계에서는 파일에 있는 전처리 지시문에 따라 소스 파일의 내용을 수정합니다. 예를 들어 #include 지시문은 헤더 파일의 내용을 .cpp 파일에 추가하는 전처리 지시문입니다. 컴파일 전에 소스 파일을 수정하는 이 방법은 다양한 컴퓨터 및 운영 체제 환경의 제약 조건에 적응할 수 있는 뛰어난 유연성을 제공합니다. 사용 가능한 하드웨어나 운영 체제가 다르기 때문에 한 환경에 필요한 코드는 다른 환경에 필요한 코드와 다를 수 있습니다. 대부분의 경우 다양한 환경에 대한 코드를 동일한 파일에 넣은 다음 전처리 단계에서 코드를 수정하여 현재 환경에 맞게 조정할 수 있습니다.

주로 다음 측면을 다룹니다.

  • #define a b와 같은 매크로 정의 지침
    • 이런 종류의 의사 명령어의 경우 사전 컴파일에서 해야 할 일은 프로그램의 모든 a를 b로 바꾸는 것뿐이지만 문자열 상수인 a는 바뀌지 않습니다. 또한 특정 매크로의 정의를 취소하여 앞으로 해당 문자열이 더 이상 대체되지 않도록 하는 #undef도 있습니다.
  • #ifdef, #ifndef, #else, #elif, #endif 등과 같은 조건부 컴파일 지시문
    • 이 의사 명령어를 도입하면 프로그래머는 다양한 매크로를 정의하여 컴파일러에서 처리할 코드를 결정할 수 있습니다. 프리컴파일러는 관련 파일을 기반으로 불필요한 코드를 필터링합니다.
  • 헤더 파일에는 #include 'FileName' 또는 #include 등과 같은 지침이 포함되어 있습니다..
    • 헤더 파일에서 #define 지시문은 일반적으로 많은 수의 매크로(가장 일반적인 매크로는 문자 상수)를 정의하는 데 사용되며 다양한 외부 기호 선언도 포함합니다. 헤더 파일을 사용하는 주요 목적은 여러 다른 C 소스 프로그램에서 특정 정의를 사용할 수 있도록 하는 것입니다. 이러한 정의를 사용해야 하는 C 소스 프로그램에서는 이 파일에서 이러한 정의를 반복할 필요 없이 #include 문만 추가하면 됩니다. 사전 컴파일러는 헤더 파일의 모든 정의를 컴파일러에서 처리하기 위해 생성하는 출력 파일에 추가합니다. C 소스 프로그램에 포함된 헤더 파일은 시스템에서 제공할 수 있습니다. 이러한 헤더 파일은 일반적으로 /usr/include 디렉터리에 위치합니다. 프로그램에 해당 항목을 #include하려면 꺾쇠 괄호()를 사용하세요. 또한 개발자는 자신만의 헤더 파일을 정의할 수도 있습니다. 이러한 파일은 일반적으로 C 소스 프로그램과 동일한 디렉터리에 배치됩니다. 이 경우 #include에 큰따옴표('')를 사용해야 합니다.
  • 특수 기호, 프리컴파일러는 일부 특수 기호를 인식할 수 있습니다
    • 예를 들어 소스 프로그램에 나타나는 LINE 로고는 현재 줄 번호(십진수)로 해석되고, FILE은 현재 컴파일된 C 소스 프로그램의 이름으로 해석됩니다. 프리컴파일러는 소스 프로그램에서 이러한 문자열의 발생을 적절한 값으로 바꿉니다.

프리컴파일러가 하는 일은 기본적으로 소스 프로그램을 "교체"하는 것입니다. 이 대체 후에는 매크로 정의, 조건부 컴파일 지침 및 특수 기호가 없는 출력 파일이 생성됩니다. 이 파일의 의미는 전처리되지 않은 소스 파일과 동일하지만 내용이 다릅니다. 다음으로, 이 출력 파일은 컴파일러의 출력으로서 기계 명령어로 변환됩니다.

컴파일 및 최적화의 두 번째 단계 미리 컴파일된 출력 파일에는 숫자, 문자열, 변수 정의 등의 상수와 main, if, else, for 등의 C 언어 키워드만 있습니다. ,while,{,}, +,-,* 등.

  • 컴파일러의 작업은 어휘 분석과 구문 분석을 사용하여 모든 명령어가 문법 규칙을 준수하는지 확인한 다음 이를 동등한 중간 코드 표현이나 어셈블리 코드로 변환하는 것입니다.
  • 최적화 처리는 컴파일 시스템에서 상대적으로 어려운 기술입니다. 이에 관련된 문제는 컴파일 기술 자체뿐만 아니라 기계의 하드웨어 환경과도 많은 관련이 있습니다. 최적화의 일부는 중간 코드의 최적화입니다. 이 최적화는 특정 컴퓨터와 독립적입니다. 또 다른 종류의 최적화는 주로 타겟 코드 생성을 목표로 합니다.
  • 전자 최적화의 경우 주요 작업은 공개 표현식 삭제, 루프 최적화(코드 추출, 강도 약화, 루프 제어 조건 변경, 알려진 수량 병합 등), 복사 전파, 쓸모 없는 할당 삭제 등입니다. 기다리다.
  • 후자의 유형의 최적화는 기계의 하드웨어 구조와 밀접한 관련이 있으며, 가장 중요하게 고려해야 할 점은 기계의 각 하드웨어 레지스터에 저장된 관련 변수의 값을 최대한 활용하여 개수를 줄이는 것입니다. 메모리 액세스. 또한 기계 하드웨어 실행 명령(예: 파이프라인, RISC, CISC, VLIW 등)의 특성에 따라 명령을 일부 조정하여 대상 코드를 더 짧게 만들고 실행 효율성을 높이는 방법도 중요합니다. 연구 주제.

Assembly: 어셈블리는 실제로 어셈블리 언어 코드를 대상 기계 명령어로 변환하는 프로세스를 나타냅니다. 번역 시스템에서 처리되는 각 C 언어 소스 프로그램에 대해 해당 대상 파일은 결국 이 처리를 통해 획득됩니다. 타겟 파일에 저장되는 것은 소스 프로그램과 동등한 타겟의 기계어 코드이다. 개체 파일은 세그먼트로 구성됩니다. 일반적으로 개체 파일에는 두 개 이상의 섹션이 있습니다.

  • Code 섹션: 이 섹션에는 주로 프로그램 지침이 포함되어 있습니다. 이 세그먼트는 일반적으로 읽고 실행할 수 있지만 일반적으로 쓸 수는 없습니다.
  • 데이터 세그먼트: 주로 프로그램에서 사용되는 다양한 전역 변수 또는 정적 데이터를 저장합니다. 일반적으로 데이터 세그먼트는 읽기, 쓰기 및 실행이 가능합니다.

UNIX 환경에는 세 가지 주요 유형의 개체 파일이 있습니다.

  • 재배치 가능한 파일: 실행 파일 또는 공유 개체 파일을 생성하기 위해 다른 개체 파일과 연결하는 데 적합한 코드 및 데이터가 포함되어 있습니다.
  • 공유 객체 파일: 이 파일은 두 가지 컨텍스트에서 연결하기에 적합한 코드와 데이터를 저장합니다. 첫 번째는 링커가 다른 재배치 가능한 파일 및 공유 개체 파일과 함께 처리하여 다른 개체 파일을 생성할 수 있다는 것이고, 두 번째는 동적 링커가 이를 다른 실행 파일 및 다른 공유 개체 파일과 결합하여 프로세스를 생성할 수 있다는 것입니다. 영상.
  • 실행 파일: 운영체제에서 생성한 프로세스에서 실행할 수 있는 파일이 포함되어 있습니다. 어셈블러가 생성하는 것은 실제로 첫 번째 유형의 개체 파일입니다. 후자의 두 가지 경우에는 이를 얻기 위해 몇 가지 다른 처리가 필요합니다. 이것이 링커의 작업입니다.

링크 과정:

어셈블러에서 생성된 객체 파일은 바로 실행되지 않으며, 해결되지 않은 문제가 많을 수 있습니다.

  • 예를 들어, 소스 파일의 함수는 다른 소스 파일에 정의된 기호(예: 변수 또는 함수 호출 등)를 참조할 수 있습니다. 라이브러리 파일의 함수는 프로그램에서 호출될 수 있습니다. 등 이 모든 문제는 링커를 통해 해결되어야 합니다.
  • 링커의 주요 임무는 관련된 대상 파일을 서로 연결하는 것, 즉 한 파일에서 참조되는 기호를 다른 파일의 기호 정의와 연결하여 이러한 모든 대상 파일이 작동 가능한 통합된 파일이 되도록 하는 것입니다. 시스템이 로드하고 실행하는 전체 내용입니다.

 개발자가 지정한 동일한 라이브러리 함수의 다양한 연결 방법에 따라 연결 프로세스는 두 가지 유형으로 나눌 수 있습니다.

  • 정적 연결: 이 연결 방법에서는 함수의 코드가 다음에서 다운로드됩니다. 최종 실행 프로그램에 복사된 정적 링크 라이브러리입니다. 이러한 방식으로 이러한 코드는 프로그램이 실행될 때 프로세스의 가상 주소 공간에 로드됩니다. 정적 링크 라이브러리는 실제로 개체 파일의 모음이며, 각 파일에는 라이브러리의 관련 기능 하나 또는 그룹에 대한 코드가 포함되어 있습니다.
  • 동적 연결: 이 방법에서는 함수의 코드가 동적 연결 라이브러리 또는 공유 개체라는 개체 파일에 배치됩니다. 이때 링커가 하는 일은 공유 객체의 이름과 기타 소량의 등록 정보를 최종 실행 프로그램에 기록하는 것이다. 이 실행 파일이 실행되면 동적 링크 라이브러리의 전체 내용이 런타임 시 해당 프로세스의 가상 주소 공간에 매핑됩니다. 동적 링커는 실행 프로그램에 기록된 정보를 기반으로 해당 기능 코드를 찾습니다.

실행 파일의 함수 호출에는 동적 링크 또는 정적 링크를 각각 사용할 수 있습니다. 동적 연결을 사용하면 최종 실행 파일을 더 짧게 만들고 여러 프로세스에서 공유 객체를 사용할 때 일부 메모리를 절약할 수 있습니다. 왜냐하면 이 공유 객체에 대한 코드 복사본 하나만 메모리에 저장하면 되기 때문입니다. 그러나 이것이 반드시 동적 링크를 사용하는 것이 정적 링크를 사용하는 것보다 우수하다는 것을 의미하지는 않습니다. 어떤 경우에는 동적 연결로 인해 성능이 저하될 수 있습니다.

관련 추천: "C 동영상 튜토리얼"

위 내용은 C 언어로 소스 파일을 컴파일하면 어떤 파일이 생성되나요?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.