-
다시한번 개발자도전! 7일차 (함수,재귀함수,메모리구조,ref,out)다시한번 개발자도전! 2026. 1. 12. 15:50
요즘 계속 앉아서 수업을 듣고 공부하니까 아랫배에 살이 찌는 느낌이다..
공부도 하고 운동도 신경써야 한다니 너모 바쁜 인생..

‼️C# 메모리 구조 (Memory Layout)
- Stack (스택): 지역 변수, 매개변수가 저장됨. 함수가 끝나면 바로 날아감. 속도가 매우 빠르지만 용량이 작음 (보통 1MB).
- Heap (힙): new 키워드로 생성된 객체(참조 타입)가 저장됨. GC(Garbage Collector)가 나중에 치워줌. 용량이 크지만 스택보다 느림.
- Static (데이터 영역): static 변수나 상수가 저장됨. 프로그램 시작할 때 생기고 끝날 때까지 살아있음.
- Code (코드 영역): 우리가 짠 프로그램 명령어(IL 코드) 자체가 저장됨. 읽기 전용임.

지역 변수 vs 전역 변수 (필드)
메모리 위치가 다르면 수명과 사용 범위도 다름.
1. 지역 변수 (Local Variable)
- 위치: Stack 영역.
- 범위: 함수 { } 안에서 선언되어 그 안에서만 살다가 함수 종료 시 소멸함.
- 특징: 초기화하지 않고 사용하면 컴파일 에러 발생.
2. 전역 변수 / 필드 (Global Variable / Field)
- 위치: 클래스 내부에 선언되며, 객체면 Heap, static이면 Static 영역.
- 범위: 클래스 전체에서 사용 가능.
- 특징: 별도 초기화를 안 해도 기본값(0, null 등)으로 자동 세팅됨.
1. 함수(Method)
특정 작업을 수행하려고 묶어둔 코드 블록임. 한 번 만들어두면 필요할 때마다 이름만 불러서 재사용할 수 있음.
- 재사용성: 똑같은 코드 또 쓸 필요 없음.
- 가독성: 코드가 의미 단위로 끊겨서 보기 편함.
- 유지보수: 한 곳만 고치면 연결된 곳이 다 바뀜.
2. 함수의 구조
반환타입 함수이름(매개변수) { // 실행할 코드 return 반환값; // 반환타입이 void가 아닐 때 }- 반환타입: 결과물로 내뱉을 데이터의 종류. 없을 땐 void를 씀.
- 매개변수(Parameter): 함수 내부로 전달받는 재료임.
예시
// 1. 주는 것도 받는 것도 없음 void SayHi() => Console.WriteLine("안녕"); // 2. 받기만 함 (매개변수 있음) void Attack(int damage) => Console.WriteLine($"{damage} 데미지!"); // 3. 받아서 계산 후 돌려줌 (반환값 있음) int Add(int a, int b) { return a + b; }🔥실습예제🔥
더보기플레이어이름:
공격력:
방어력:
민첩:
스피드:
static void Main(string[] args) { PlayerInFo("뭉뭉", 100, 50, 70, 100); } static void PlayerInFo(string name,float atk, float def,float speed,float luk ) { Console.WriteLine($"이름: {name}"); Console.WriteLine($"공격력: {atk}"); Console.WriteLine($"방어력: {def}"); Console.WriteLine($"민첩: {speed}"); Console.WriteLine($"행운: {luk}"); }💡 명명된 인수 & 선택적 매개변수
더보기- 매개변수에 기본값을 설정해두면 호출할 때 생략이 가능함. 특정 값만 넣고 싶을 땐 **이름(name:)**을 지정하면 됨.
static void Main() { // num은 기본값(100) 쓰고, num2만 10.5f로 지정함 Fun(num2: 10.5f); } static void Fun(int num = 100, float num2 = 1.5f) { }3.함수의 오버로딩
- "이름은 같지만 매개변수가 다른" 함수들을 만드는 기술임. 비슷한 기능을 하는 함수들을 하나의 이름으로 관리할 수 있어 편리함.
- 주의: 반환 타입만 다른 것은 오버로딩이 안 됨! 매개변수(개수, 타입)가 반드시 달라야 함.
static void Main(string[] args) { Fun(); Fun(1); } static void Fun() { } //이름은 같지만 매개변수를 다르게 하여 사용가능ㅇ static void Fun(int i) { }
ref 와 out
- C#에서 값 타입은 함수에 넘길 때 복사본이 전달됨. 함수 안에서 값을 바꿔도 원본은 안 변함. ref와 out을 쓰면 원본을 직접 수정할 수 있음.
1. ref (Reference: 참조)
함수 외부에서 이미 초기화된 변수를 함수 안에서 수정하고 싶을 때 씀.
- 특징: 함수에 넣기 전에 반드시 값이 들어있어야 함.
- 용도: 기존 데이터의 값을 업데이트할 때.
internal class Program { //매개변수 int a 대신받아준다. static void Attack(ref int a) { Console.WriteLine("공격력 : " + a); a++; } static void Main(string[] args) { //ref 키워드 참조 //C# 내부적으로 포인터 개발자들이 신경덜쓰게 잘만들어놓음 int a = 10; Attack(ref a); Console.WriteLine("a 값 : " + a); } }2. out (Output: 출력)
함수 내부에서 값을 만들어 밖으로 내보낼 때 씀.
- 특징: 함수 내부에서 반드시 값을 할당해야 함. (안 하면 에러 남)
- 용도: 한 함수에서 여러 개의 결과값을 반환하고 싶을 때 유용함.
static void Main() { int playerHp; // 초기화 안 해도 됨 SetStartStats(out playerHp); Console.WriteLine($"초기 HP: {playerHp}"); // 100 } static void SetStartStats(out int hp) { hp = 100; // 함수 안에서 반드시 값을 채워줘야 함! }3. ref 와 out 의 차이
구분 ref out 목적 기존 데이터를 수정함 데이터를 생성해서 내보냄 초기화 호출 전 반드시 초기화 필요 호출 전 초기화 안 해도 됨 함수 내부 값을 수정 안 해도 됨 반드시 값을 할당해야 함
재귀함수 (Recursion)
- **"자기 자신을 다시 호출하는 함수"**
- 큰 문제를 해결하기 위해 동일한 방식으로 작동하는 더 작은 문제로 쪼개서 푸는 방식임.
1. 재귀함수의 필수 조건 (중요!)
- 기초 케이스 (Base Case): 재귀를 멈추는 조건. (언제 끝날 것인가?)
- 재귀 단계 (Recursive Step): 문제를 더 작게 쪼개서 자기 자신을 호출하는 부분.
static void Main() { int result = Factorial(5); Console.WriteLine(result); // 120 } static int Factorial(int n) { // 1. 기초 케이스: n이 1이면 1을 반환하고 끝냄 if (n <= 1) return 1; // 2. 재귀 단계: n과 (n-1)의 팩토리얼을 곱함 return n * Factorial(n - 1); }
이제는 개인프로젝트를 어떤걸 할지 한번 구상해 봐야겠다
멀티로 만들고 싶긴한데 시간이 오래 걸릴것 같아 고민쑤..
그래도 일단 도전! 아좌조자!

'다시한번 개발자도전!' 카테고리의 다른 글
다시한번 개발자도전! 8일차(클래스,생성자,접근제한자,프로퍼티) (0) 2026.01.13 c# 컬렉션(Collection)/List,Dictionary,Stack,Queue (3) 2026.01.12 다시한번 개발자도전! 6일차 (배열,컬렉션) (0) 2026.01.09 다시한번 개발자도전! 5일차 (이중반복문 , 콘솔 좌표이동) (0) 2026.01.08 다시한번 개발자도전! 4일차(삼항연산자,연산자 우선순위,제어문,반복문) (0) 2026.01.07