[C/C++] 14. 함수(2)

찰규

·

2026년 8월 31일 (오늘)

앞서 printfscanf를 통한 표준 입출력 및 메모리 주소 전달 방식을 알아보았다. 이번 글에서는 함수가 호출되고 반환되는 전체적인 실행 흐름, 후입선출(LIFO) 원리를 따르는 스택(Stack) 자료구조, 그리고 함수 실행 시 스택 메모리 영역의 할당과 해제 원리를 정리한다.

1. 프로그램 실행 흐름과 함수 호출의 중첩

C/C++ 프로그램은 가장 먼저 main 함수에서 실행을 시작하며, main 함수가 종료될 때 프로그램 전체가 종료된다.

  • 함수의 중첩 호출: main 함수 내부에서 다른 함수를 호출하고, 그 함수가 또 다른 함수를 연쇄적으로 호출할 수 있다.

  • 제어 흐름의 전환: 함수 호출 -> 내부 로직 실행 -> 결과값 반환(Return) -> 호출한 위치로 복귀의 단계를 거친다. 즉, 호출된 하위 함수가 완전히 종료되어야만 이를 호출했던 상위 함수가 다음 코드를 이어갈 수 있다.

2. 스택(Stack) 자료구조와 함수 호출 메커니즘

함수의 호출 및 종료 메커니즘은 자료구조의 스택(Stack) 원리와 정확히 일치한다.

stack

  • 스택(Stack, LIFO / FILO): 접시를 차곡차곡 쌓아 올리는 것처럼, 가장 나중에 들어간 데이터가 가장 먼저 나오는 후입선출(Last In First Out) 구조다.

  • 큐(Queue, FIFO): 줄을 서는 것처럼 먼저 들어간 데이터가 먼저 나가는 선입선출(First In First Out) 구조로, 스택과 대비된다.

  • 함수 호출의 적용: 가장 먼저 실행된 main 함수는 스택의 가장 밑에 쌓이고, 그 위로 호출되는 함수들이 차례로 쌓인다. 나중에 호출된 함수가 작업을 마치고 스택에서 빠져나가야 비로소 이전 함수로 제어권이 돌아온다.

3. 스택 메모리(Stack Memory)의 할당과 해제

함수가 실행될 때 사용하는 메모리 공간을 스택 영역이라고 부른다.

#include <stdio.h>

int Add(int a, int b) {
    int result = a + b; // Add 함수의 지역 변수
    return result;
} // 함수 종료 시 Add 함수의 스택 메모리 자동 해제

int main() {
    int x = 10;
    int y = 20;
    int sum = Add(x, y); // Add 함수 호출 시 스택 메모리 할당
    
    printf("결과: %d\n", sum);
    return 0;
}
  1. 호출 시 메모리 할당: 함수가 호출되면 컴파일 시점에 계산된 크기만큼 스택 프레임(Stack Frame)이 할당되며, 매개변수와 내부 지역 변수들이 이 공간에 생성된다.

  2. 종료 시 메모리 해제: 함수가 return을 만나 종료되는 즉시, 해당 함수가 점유하던 스택 메모리는 통째로 반환(해제)된다.

  3. 변수 스코프의 독립성: 서로 다른 함수에서 같은 이름의 변수(int a)를 선언해도 충돌하지 않는 이유는, 각 함수마다 독립된 스택 메모리 영역에 변수가 존재하기 때문이다.

4. 코드(명령어)와 메모리(데이터 공간)의 분리

프로그래밍을 학습할 때 흔히 작성한 '코드' 자체를 메모리 공간과 혼동하기 쉽다. 하지만 둘은 명확히 구분된다.

  • 코드(Code): CPU가 어떤 작업을 수행해야 하는지 적어둔 명령어의 집합(설계도/작업 지시서)이다.

  • 메모리(Memory): 명령어가 실행되면서 실제로 변수가 만들어지고 데이터가 기록되는 실제 작업 공간(토지/공간)이다.

함수가 종료된다고 해서 작성된 '코드'가 사라지는 것이 아니라, 코드가 실행되면서 스택 영역에 잡혔던 '메모리'가 해제되는 것이다.

마무리하며

  • 함수 호출과 반환은 가장 나중에 호출된 함수가 먼저 종료되는 스택(후입선출, LIFO) 방식을 따른다.

  • 함수 내부의 지역 변수와 매개변수는 함수 호출 시 스택 메모리에 할당되고, 함수 종료 시 즉시 해제된다.

  • 코드는 실행할 명령어 집합이며, 실제 데이터가 생성되고 소멸하는 메모리 공간과 분리해서 이해해야 한다.