함수 (Function)
함수는 특정 작업을 수행하는 코드의 묶음이다.
같은 코드를 여러 번 작성하지 않고 재사용할 수 있으며, 프로그램을 기능별로 분리하여 관리할 수 있게 해준다.
함수 선언
기본 문법
반환형 함수이름(매개변수)
{
실행할 코드
}
예시
int Add(int a, int b)
{
return a + b;
}
사용
int result = Add(10, 20);
실행 결과
30
함수의 구성 요소
int Add(int a, int b)
{
return a + b;
}
| 구성 요소 | 설명 |
|---|---|
| int | 반환형(Return Type) |
| Add | 함수 이름 |
| int a, int b | 매개변수(Parameter) |
| return | 반환 값 |
함수 호출
Add(10, 20);
함수를 호출하면 함수 내부 코드가 실행된다.
int result = Add(10, 20);
↓
int result = 30;
return
함수의 결과 값을 호출한 곳으로 돌려준다.
int Add(int a, int b)
{
return a + b;
}
반환값이 없는 함수
void PrintHello()
{
cout << "Hello";
}
void는 반환값이 없다는 의미이다.
함수와 메모리
함수 자체는 코드 영역(Code Segment) 에 저장된다.
int Add(int a, int b)
{
return a + b;
}
프로그램이 시작될 때 코드 영역에 적재된다.
함수 호출 시 일어나는 일
Add(10, 20);
함수를 호출하면 스택(Stack) 영역에 함수 실행을 위한 정보가 저장된다.
호출 흐름
함수 호출
↓
매개변수 저장
↓
리턴 주소 저장
↓
함수 실행
↓
함수 종료
↓
스택 정리
↓
호출한 위치로 복귀
예시
int Add(int a, int b)
{
int result = a + b;
return result;
}
int main()
{
Add(10, 20);
}
스택
┌────────────┐
│ result │
├────────────┤
│ b = 20 │
├────────────┤
│ a = 10 │
├────────────┤
│ 리턴 주소 │
└────────────┘
함수 종료 시 모두 제거된다.
매개변수 전달 방식
값 전달 (Call by Value)
매개변수의 값을 복사하여 전달한다.
원본 데이터는 변경되지 않는다.
void Func(int x)
{
x = 100;
}
int main()
{
int num = 10;
Func(num);
cout << num;
}
실행 결과
10
메모리 구조
main의 num = 10
↓ 복사
Func의 x = 10
x만 변경되고 원본은 변경되지 않는다.
주소 전달 (Pointer)
변수의 주소를 전달한다.
포인터 자체는 값으로 전달되지만, 주소를 통해 원본 데이터에 접근할 수 있다.
void Func(int* x)
{
*x = 100;
}
사용
int num = 10;
Func(&num);
실행 결과
100
메모리 구조
num = 10
Func(&num)
x -----> num
포인터가 원본을 가리키므로 원본이 변경된다.
참고
포인터는 엄밀히 말하면
Call by Value
이다.
주소값을 복사해서 전달하기 때문이다.
int* x
도 결국 포인터 변수 하나가 복사되어 전달된다.
참조 전달 (Call by Reference)
원본 변수 자체를 참조한다.
void Func(int& x)
{
x = 100;
}
사용
int num = 10;
Func(num);
실행 결과
100
메모리 구조
num = 10
x ↔ num
x와 num은 같은 데이터를 가리킨다.
전달 방식 비교
| 방식 | 원본 변경 |
|---|---|
| 값 전달 (Call by Value) | ❌ |
| 포인터 전달 | ⭕ |
| 참조 전달 (Call by Reference) | ⭕ |
스택 프레임 (Stack Frame)
함수가 호출될 때 스택에 생성되는 함수 실행 정보 묶음을 말한다.
스택 프레임에 저장되는 것
void Func(int a)
{
int b = 10;
}
스택 프레임
┌────────────┐
│ 지역변수 b │
├────────────┤
│ 매개변수 a │
├────────────┤
│ 리턴 주소 │
├────────────┤
│ 레지스터 백업 │
└────────────┘
함수 종료 시
Func();
↓
스택 프레임 생성
↓
함수 실행
↓
스택 프레임 제거
↓
호출 위치로 복귀
재귀 함수와 스택 프레임
함수가 자기 자신을 호출하는 것을 재귀 함수라고 한다.
void Func(int n)
{
if (n == 0)
return;
Func(n - 1);
}
호출
Func(3);
스택
Func(3)
└─ Func(2)
└─ Func(1)
└─ Func(0)
함수마다 새로운 스택 프레임이 생성된다.
정리
- 함수는 특정 기능을 수행하는 코드 묶음이다.
- 함수 자체는 코드 영역(Code Segment)에 저장된다.
- 함수 호출 시 스택 영역에 실행 정보가 생성된다.
- 함수 종료 시 스택 프레임이 제거된다.
- 값 전달(Call by Value)은 원본이 변경되지 않는다.
- 포인터 전달은 주소를 통해 원본을 변경할 수 있다.
- 참조 전달(Call by Reference)은 원본 자체를 참조한다.
- 함수 호출 시 생성되는 실행 정보 묶음을 스택 프레임(Stack Frame)이라고 한다.