본문 바로가기
Tech/Coding

C언어 기본] 01 프로그램 만들기

by redcubes 2024. 3. 4.

void 요약(혼공C) {

  • C는 UNIX에서 쓰려고 개발;
  • 컴파일 = 소스코드컴파일러기계어과정을 말한다;
  • 비주얼 스튜디오는 컴파일러의 일종이라고 나와 있다. (내 생각엔 여러 컴파일러를 포함한 IDE 같다.);
  • 유용한 단축키 Ctrl+Shift+B(컴파일) Ctrl+F5(실행)
  • (소스)전처리(전처리 소스)컴파일(목적파일)링크(실행파일)

}

void 예시(검색 결과, Chat GPT) {

#include <stdio.h>

int main() {
    printf("Hello, World!\n");
    return 0;
}

이 프로그램은 표준 출력에 "Hello, World!"를 출력합니다. 각 단계별로 파일이 어떻게 변화하는지 살펴보겠습니다.

1. 전처리(Preprocessing) 단계

  • 목적: 소스 코드에서 #include와 같은 전처리 지시문을 처리합니다. 이 단계에서는 #include <stdio.h> 같은 지시문이 처리되어 해당 헤더 파일의 내용이 소스 파일에 포함됩니다.
  • 변화: 전처리기는 #include 지시문을 처리하여 stdio.h의 내용을 포함시킨 새로운 소스 코드를 생성합니다. 사용자가 작성한 코드 외에도 표준 입출력 함수 등의 선언이 추가됩니다. 이 결과는 일반적으로 사용자에게 보이지 않으며, 컴파일러가 내부적으로 처리합니다.
    // 예시: 실제로는 stdio.h 내부의 많은 선언들 중 일부만 포함됩니다.
    int printf(const char *format, ...);
    
    int main() {
        printf("Hello, World!\n");
        return 0;
    }​

 

2. 컴파일(Compilation) 단계

  • 목적: 전처리된 소스 코드를 기계어로 번역하는 단계입니다. 소스 코드를 컴퓨터가 이해할 수 있는 오브젝트 파일로 변환합니다.
  • 변화: 컴파일러는 전처리된 소스 코드를 분석하여 중간 표현 형태(assembly code)로 변환한 다음, 이를 기계어로 번역합니다. 결과물은 .o 또는 .obj 확장자를 가진 오브젝트 파일입니다. 이 파일은 실행 가능한 프로그램이 아니라, 기계어로 번역된 코드의 모음입니다.
    // main 함수에서 printf 함수를 호출하는 기계어 코드가 포함되어 있으며, 
    // 실행 가능한 최종 파일을 생성하기 위한 정보와 함께 
    // 메타데이터, 심볼 테이블 등이 포함
    
    [기계어 코드] [메타데이터] [심볼 및 참조 정보]​

3. 링크(Linking) 단계

  • 목적: 하나 이상의 오브젝트 파일을 결합하여 실행 가능한 프로그램을 생성합니다. 이 단계에서는 외부 라이브러리 함수 호출(예: printf)에 필요한 참조를 해결합니다.
  • 변화: 링커는 필요한 라이브러리 함수들(예를 들어, stdio.h에 정의된 printf)과 사용자가 정의한 오브젝트 파일들을 함께 묶어 실행 가능한 파일을 생성합니다. 결과물은 일반적으로 .exe(윈도우 환경) 또는 단순히 실행 파일(리눅스나 유닉스 환경)입니다. 이 파일은 운영체제가 직접 실행할 수 있는 형태입니다.
    //이 파일 내부에는 main 함수와 printf 함수의 실제 코드가 모두 포함되어 있으며, 
    //운영체제가 이해할 수 있는 형태로 구성되어 있습니다. 
    //실행 파일 내부는 대략적으로 다음과 같은 구조를 갖습니다.
    [프로그램 코드] [라이브러리 함수 코드] [데이터] [실행에 필요한 메타데이터]​

이 과정을 통해 간단한 C 프로그램은 사용자가 작성한 소스 코드에서 시작하여 실행 가능한 파일로 변화합니다. 각 단계는 소스 코드를 효율적이고 정확하게 기계어로 변환하는 데 필수적인 역할을 합니다.

void 정리{

1. 전처리: 전처리(preprocessing)는 C 및 C++과 같은 프로그래밍 언어에서 소스 코드가 컴파일러에 의해 컴파일되기 전에 수행되는 초기 처리 단계입니다. 전처리 과정은 전처리기(preprocessor)에 의해 수행되며, 이 단계에서는 주로 매크로 치환, 파일 포함, 조건부 컴파일 등의 작업이 이루어집니다. 전처리기는 소스 코드 파일을 입력으로 받아, 지시어(directives)에 따라 코드를 변환하고, 결과적으로 변환된 코드를 컴파일러가 처리할 수 있는 형태로 출력합니다.

전처리기가 수행하는 주요 작업은 다음과 같습니다:

매크로 치환(Macro Replacement): #define 지시어를 사용하여 정의된 매크로는 소스 코드 내에서 해당 매크로 이름이 나타날 때마다 미리 정의된 코드 또는 값으로 치환됩니다.

파일 포함(File Inclusion): #include 지시어를 사용하여 다른 파일의 내용을 현재 파일에 포함시킵니다. 표준 라이브러리 헤더 파일이나 사용자 정의 헤더 파일을 포함시키는 데 사용됩니다.

조건부 컴파일(Conditional Compilation): #if, #ifdef, #ifndef, #else, #elif, #endif 등의 지시어를 사용하여 특정 조건을 만족할 때만 코드가 컴파일되도록 할 수 있습니다. 이를 통해 플랫폼이나 컴파일러에 특정한 코드를 조건적으로 포함시킬 수 있습니다.

오류 지시와 줄 번호 제어(Error Directive and Line Control): #error와 #line 지시어를 사용하여 컴파일 시 오류 메시지를 생성하거나, 소스 코드의 줄 번호를 제어할 수 있습니다.

프래그마 지시어(Pragma Directives): #pragma 지시어는 컴파일러에 특정한 명령을 내리기 위해 사용됩니다. 컴파일러마다 다르게 해석될 수 있으며, 최적화 옵션 설정 등에 사용됩니다.

전처리 과정은 프로그램의 최종 실행 파일이 생성되기 전 필수적인 단계로, 소스 코드의 가독성, 재사용성, 이식성을 향상시키는 데 도움을 줍니다. 전처리기 지시어는 # 기호로 시작하며, 이는 컴파일러가 아닌 전처리기에게 작업을 지시하는 것임을 의미합니다.

2. 컴파일: 목적파일 생성-CPU이해 가능하지만 os 가 인식할 수 있게 바꿔야.

3. 링크: 목적 파일에 startup code 결합- 프로그램 실행 전 필요한 준비 작업 수행 main함수 호출
C 언어에서 스타트업 코드(startup code)는 프로그램이 실행되기 전 필요한 여러 초기 설정을 수행하는 코드를 말합니다. 이 코드는 프로그램의 실행 파일이 메모리에 로드되고 main 함수가 호출되기 전에 실행되며, 스택 초기화, 전역 변수의 메모리 할당 및 초기화, 표준 라이브러리 및 다른 필수 라이브러리의 초기화 등을 포함할 수 있습니다. C 언어 프로그램의 실행 과정에서 이 스타트업 코드는 컴파일러와 링커에 의해 자동으로 처리되며, 개발자가 직접 작성하는 경우는 드뭅니다.

스타트업 코드는 보통 어셈블리 언어로 작성되어 있으며, 컴파일러나 링커가 제공하는 라이브러리에 포함되어 있습니다. 다음은 C 언어 스타트업 코드가 수행할 수 있는 일반적인 작업들입니다:

  1. 데이터 세그먼트 및 BSS 세그먼트 초기화: 전역 변수와 정적 변수에 대한 메모리를 할당하고 초기화합니다. 데이터 세그먼트는 초기화된 전역 변수와 정적 변수를 위한 공간을, BSS(Block Started by Symbol) 세그먼트는 초기화되지 않은 전역 변수와 정적 변수를 위한 공간을 갖습니다.
  2. 힙 및 스택 초기화: 프로그램이 실행되는 동안 동적 메모리 할당과 함수 호출을 위해 사용되는 힙과 스택의 경계를 설정합니다.
  3. 표준 라이브러리 및 실행 환경 초기화: 표준 입출력 라이브러리 같은 필수 라이브러리의 초기화를 수행하고, 프로그램 실행을 위한 환경을 준비합니다.
  4. main 함수 호출: 모든 초기화 작업이 완료된 후, 스타트업 코드는 프로그램의 진입점인 main 함수를 호출합니다.
  5. 프로그램 종료 처리: main 함수의 실행이 끝나면, 스타트업 코드는 프로그램의 종료 코드를 운영 체제에 반환하고, 필요한 종료 처리 작업을 수행합니다.

C 언어 스타트업 코드는 대부분의 개발자가 일반적으로 접근하거나 수정하지 않는 부분이지만, 내장 시스템이나 특수한 실행 환경에서는 개발자가 스타트업 코드를 직접 조작하거나 커스텀 스타트업 코드를 작성해야 할 수도 있습니다. 이러한 경우, 개발자는 해당 플랫폼의 실행 메커니즘과 하드웨어 세부 사항에 대한 깊은 이해가 필요합니다.

https://kimvampa.tistory.com/27

 

컴파일(Compile), 링크(Link), 빌드(Build) 정리

개인공부 후 자료를 남기기 위한 목적이기에 내용 상에 오류가 있을 수 있습니다. 목표 컴파일, 링크, 빌드 전체 과정을 이해한다. 컴파일, 컴파일러 개념 링크, 링커 개념 빌드, 빌드툴 개념 빌

kimvampa.tistory.com

 

https://backendcode.tistory.com/161

 

[IT 기술 면접] JVM (자바 가상 머신) 이란?

이번에는 JVM에 대해 정리할 것이다. ▶ JVM 이란? JVM이란 Java Virtual Machine, 자바 가상 머신의 약자를 따서 줄여 부르는 용어이다. (가상 머신이란 프로그램을 실행하기 위해 물리적 머신과 유사한

backendcode.tistory.com

 

https://kkhipp.tistory.com/178

 

Startup code 스타트업 코드

Startup Code 부팅 과정 중 첫번째에 실행되는 코드, 말그대로 시작할 때 필요한 사항을 적은 코드입니다. main함수가 불리기 전에 실행되죠. 파일명이 startup.s 입니다. 파일명.c는 어셈블리어로 프로

kkhipp.tistory.com

https://gcc.gnu.org/

 

GCC, the GNU Compiler Collection - GNU Project

GCC, the GNU Compiler Collection The GNU Compiler Collection includes front ends for C, C++, Objective-C, Fortran, Ada, Go, and D, as well as libraries for these languages (libstdc++,...). GCC was originally written as the compiler for the GNU operating sy

gcc.gnu.org

https://namu.wiki/w/GCC

 

GCC

G NU C ompiler C ollection, GCC GNU 프로젝트의 오픈 소스 컴파일러 컬렉션.

namu.wiki

GCC(GNU Compiler Collection)와 GNU C는 서로 밀접하게 연관되어 있지만, 각각 다른 역할을 하는 소프트웨어입니다. 간단히 설명하면, GCC는 다양한 프로그래밍 언어를 위한 컴파일러 모음이고, GNU C는 C 프로그래밍 언어를 위한 표준 라이브러리의 구현입니다. 각각에 대해 더 자세히 설명하겠습니다.

GCC (GNU Compiler Collection)

  • 정의: GCC는 C, C++, Objective-C, Fortran, Ada, Go, D 등 다양한 프로그래밍 언어를 컴파일할 수 있는 자유-오픈 소스 컴파일러 모음입니다. 원래는 GNU C Compiler로, 오직 C 언어만을 위한 컴파일러였지만, 시간이 지나면서 여러 다른 언어도 지원하게 되어 이름이 GNU Compiler Collection으로 변경되었습니다.
  • 역할: 소스 코드를 받아서 기계어로 번역하는 역할을 합니다. 이 과정에서 다양한 최적화를 수행하여 실행 파일의 성능을 향상시킬 수 있습니다.
  • 특징: GCC는 다양한 플랫폼에서 사용될 수 있으며, 크로스 컴파일러로도 사용될 수 있습니다. 즉, 한 시스템에서 다른 시스템을 위한 실행 파일을 생성할 수 있습니다.

GNU C

  • 정의: GNU C는 GNU 프로젝트의 일부로서, C 표준(예: ISO C99, ISO C11)을 구현하는 C 언어 표준 라이브러리입니다. 이 라이브러리는 glibc(GNU C Library)로도 알려져 있으며, 시스템 호출 래퍼, 기본 데이터 타입, 입출력 처리 등의 기능을 제공합니다.
  • 역할: 프로그램이 운영체제와 상호작용할 수 있게 해주며, 파일 조작, 메모리 할당, 문자열 처리 등의 공통적인 작업을 수행하는 함수들을 포함합니다.
  • 특징: glibc는 리눅스 기반 시스템에서 가장 널리 사용되는 C 표준 라이브러리 구현 중 하나입니다. POSIX와 같은 표준에 대한 광범위한 지원을 제공하며, GNU 시스템의 핵심 구성 요소 중 하나입니다.

상호 관계

GCC와 GNU C(glibc)는 함께 사용되어 강력한 개발 환경을 제공합니다. GCC가 프로그램의 소스 코드를 컴파일하고, GNU C 라이브러리는 실행 시 필요한 기본적인 인터페이스와 함수를 제공합니다. 예를 들어, printf 함수는 GNU C 라이브러리에 정의되어 있으며, GCC를 사용하여 컴파일된 프로그램은 이 함수를 호출할 수 있습니다.

이 두 소프트웨어는 GNU 프로젝트의 중요한 부분이며, 리눅스를 비롯한 많은 UNIX-like 시스템에서 기본 개발 도구로 사용됩니다.

https://velog.io/@bcj0114/%EC%BB%B4%ED%8C%8C%EC%9D%BC%EB%9F%AC%EC%99%80-%EC%9D%B8%ED%84%B0%ED%94%84%EB%A6%AC%ED%84%B0-%EA%B7%B8%EB%A6%AC%EA%B3%A0-JIT-%EC%BB%B4%ED%8C%8C%EC%9D%BC

 

컴파일러와 인터프리터, 그리고 JIT 컴파일

전통적인 입장에서 컴퓨터 프로그램을 만드는 방법은 두 가지가 있다.정적 컴파일 방식인터프리트 방식정적 컴파일 방식을 사용하는 언어 번역 프로그램 원시 코드(소스 코드)고급 프로그래밍

velog.io

간단한 C 프로그램의 소스 코드에서 어셈블리 코드로 컴파일된 예제를 보여드리겠습니다. 다음은 아주 기본적인 C 프로그램입니다.

#include <stdio.h>

int main() {
    printf("Hello, World!\n");
    return 0;
}

이 프로그램을 컴파일하고 어셈블리 코드를 생성하기 위해서는 GCC 컴파일러의 -S 옵션을 사용합니다. 다음은 커맨드 라인 명령어의 예시입니다.

gcc -S main.c

이 명령은 main.c 소스 파일을 컴파일하고, 같은 디렉토리에 main.s라는 어셈블리 코드 파일을 생성합니다. 어셈블리 코드의 정확한 내용은 사용하는 컴파일러의 버전, 타겟 아키텍처, 그리고 컴파일러의 최적화 옵션에 따라 달라질 수 있습니다.

아래는 생성될 수 있는 어셈블리 코드의 간략화된 예시입니다. 실제 코드는 훨씬 복잡하고, 시스템 호출, 레지스터 할당 등을 포함할 것입니다.

.globl main
main:
    pushq %rbp
    movq %rsp, %rbp
    leaq .LC0(%rip), %rdi
    call puts
    movl $0, %eax
    popq %rbp
    ret
.LC0:
    .string "Hello, World!\n"

이 예시에서는 간단한 “Hello, World!” 프로그램의 어셈블리 버전을 보여줍니다. printf 대신 puts 함수를 호출하는 최적화가 적용될 수도 있습니다. 또한, 이 코드는 특정 아키텍처(예: x86_64)를 대상으로 한 것이며, 다른 아키텍처에서는 다를 수 있습니다.

어셈블리 코드를 이해하고 싶다면, 기본적인 어셈블리 언어와 컴퓨터 아키텍처에 대한 지식이 필요합니다. 어셈블리 코드는 기계어와 매우 밀접하게 연관되어 있으며, 프로세서의 명령어 세트 아키텍처(ISA)를 직접적으로 반영합니다.

'Tech > Coding' 카테고리의 다른 글

C언어 기본] 배열  (0) 2024.03.22
🐨그리디 알고리즘  (3) 2024.03.19
10844번 쉬운 계단 수  (0) 2024.03.03
나의 방학  (0) 2024.03.02
가장 가까운 두 점  (0) 2024.03.02