const 심화(compile time, runtime, constexpr, if)

김펭귄·2025년 7월 17일

C++

목록 보기
3/20

Compile time과 Runtime

컴파일 타임(Compile Time)

  • 소스 코드가 컴파일러에 의해 기계어로 번역되어 실행파일로 만들어지는 과정
  • 코드의 문법(Syntax)과 타입(Type) 오류를 검사하여 컴파일 타임 오류 발생시킴
  • 최적화 작업도 이 단계에서 일부 수행
  1. 전처리(Preprocessing)

    • 먼저 #include, #define 등의 전처리 지시문 처리
    • 결과: 소스코드가 확장된 임시 파일(텍스트 형태) 생성
  2. 컴파일(Compilation)

    • 전처리된 소스코드를 컴파일러가 어셈블리어(assembler code) 또는 바로 기계어(binaries)로 변환
    • 결과 : 오브젝트 파일(.obj) 생성
  3. 어셈블(필요할 경우)

    • 컴파일러가 어셈블리로 변환한 것을 어셈블러가 기계어 바이너리 코드로 재변환
    • 현대 컴파일러는 이 과정을 자동으로 내부에서 처리해 바로 obj 파일로 생성
  4. 링킹(Linking)

    • 여러 .obj 파일과 라이브러리 파일(.lib 등)을 링커(linker)가 결합해 실행파일(.exe) 생성
  • 위 모든 과정은 컴파일 타임(소스코드 빌드)에서 이루어짐
  • 결과로 디스크에 .exe 파일 생성

런타임(Runtime)

  • 컴파일 타임 이후에 컴파일된 프로그램(.exe)이 실행되는 시점으로 코드의 명령들이 실제로 동작
  • 입출력, 계산, 파일 읽기/쓰기, 동적 메모리 할당, 예외 처리 등의 작업들이 런타임에서 이루어짐
  • 0으로 나누기, 없는 파일 열기, 메모리 부족, 널 포인터 접근 등의 오류는 런타임 오류라고 하며, 실행되는 도중인 런타임 중에 발생

constexpr

  • const 는 값의 불변을 의미하나 컴파일 또는 런타임에 값이 결정될 수 있음
int input;
std::cin >> input;       // 런타임에 값 입력
const int number = input; // 마찬가지로 런타임에 값이 결정됨
void func(int param) {
// 함수 호출 시 결정되는 값으로, 어느 값이 들어올지는 런타임에 결정됨
    const int myConst = param; 
}     						 
  • constexprconst (값 불변) + 컴파일 타임에 값이 결정됨

  • 따라서 constexpr 변수는 constant expression(상수 표현식)으로 정의되어야 함

constant expression(상수 표현식)

  • 프로그램을 빌드(컴파일)할 때 이미 값이 결정되어, 실행 시에는 계산이 필요 없는 값
  • 10, 3.14, 'A', true, nullptr과 같은 리터럴은 상수 표현식
  • 이미 constexpr인 변수나 함수의 반환값도 상수 표현식
int foo()	// 함수는 런타임에 실행됨
{
    return 5;
}

int main()
{
    constexpr double pi { 3.14 }; // ok: 3.14는 상수 표현식
    constexpr int sum { 4 + 5 };      // ok: 4 + 5도 상수 표현식
    constexpr int x { sum };  // ok: sum도 상수표현식이므로 가능

    int len{};
    std::cin >> len;		// 런타임에 값 결정됨
    
	// compile error: len은 런타임에 값이 결정되므로 상수 표현식이 아님
    constexpr int ruler {len};   
    
    // compile error: 함수는 보통 런타임에 실행되므로 반환값도 런타임에 결정되어 불가능
    constexpr int f { foo() };     
}

constexpr 장점

  • 배열의 크기, 템플릿 인자처럼 컴파일 타임 상수만 허용하는 영역에 사용 가능
int x{};
std::cin >> x;  	// 런타임에 입력 받음
const int n = x;	// const지만 런타임에 값이 결정됨
int arr[n]{};		// compile error: 배열의 크기는 컴파일 타임 상수만 가능

constexpr int y{5};	// 컴파일 타임에 값 결정
int arr[y]{};		// 사용 가능
  • constexpr을 통해 함수도 상수 표현식으로 사용 가능
  • 전달받는 인자가 컴파일 타임에 결정되고(상수 표현), 함수의 내용이 재귀, 반복, 조건문 정도만 있으면 컴파일 타임 또는 런타임에 결정된다
  • constexpr 함수는 자신이 속한 상수 표현식이 컴파일 타임에 계산되어야 하는 경우에 컴파일 타임에 계산됨
constexpr int square(int x) { return x * x; } // 컴파일 타임에 실행됨

int main() 
{
	// 매개인자가 상수(5)이고, 함수 역시 constexpr이므로 가능
	constexpr int val = square(5); // 컴파일 타임에 반환값 결정
  • 일반 함수와의 차이점
int max(int x, int y) // 일반 함수. 런타임에 실행됨
{
    if (x > y)
        return x;
    else
        return y;
}

constexpr int cmax(int x, int y) // constexpr 함수. 컴파일 타임에 결정됨
{
    if (x > y)
        return x;
    else
        return y;
}

int main()
{
    int m1 { max(5, 6) };            // ok
    const int m2 { max(5, 6) };      // ok
    constexpr int m3 { max(5, 6) };  // compile error: max()는 상수 표현식 아님

    int m4 { cmax(5, 6) };           // ok: 컴파일 or 런타임에 결정
    const int m5 { cmax(5, 6) };     // ok: 컴파일 or 런타임에 결정
    constexpr int m6 { cmax(5, 6) }; // ok: 컴파일 타임에 결정

    return 0;
}

constexpr if

  • compile time에 결정되는 조건을 런타임에 if 문에서 참/거짓을 판단하는 것은 비효율적
constexpr double gravity{ 9.8 };	// compile time
if (gravity == 9.8) { return 1; }	// 런타임에 판단
  • C++17부터는 constexpr if문을 통해 상수식을 이용한 조건문을 compile time에 실행되도록 함
constexpr double gravity{ 9.8 };
if constexpr (gravity == 9.8) { return 1; }	// compile time에 실행
  • 조건이 참이므로, 아래와 같이 컴파일 됨
constexpr double gravity{ 9.8 };
return 1;

Reference

learn.cpp

profile
반갑습니다

0개의 댓글