포인터 타입 변수와 동적 할당
포인터란?
•
숫자를 저장하고 싶다 → int 타입 변수를 사용한다
•
글자를 저장하고 싶다 → char 타입 변수를 사용한다
•
주소 값을 저장할 수 있는 타입을 포인터 타입 변수라고 한다
int main()
{
// 📍 포인터 타입 목적
unsigned int addressNumber = 0;
// 주소는 숫자니까 사실 안 됨에 저장해도 상관이 없다.
int a = 0;
addressNumber = (unsigned int)&a; // 강제 형변환으로 주소를 숫자로
// 💡 포인터 변수에 * 을 정에서
// 해당 주소에 위치(변수)를 이동할 수 있다.
// 또는 가르킨다 라고 한다.
int* p = &a; // p는 a의 주소를 저장
*p = 100; // p가 가리키는 곳(a)에 100 저장
return 0;
}
C++
복사
메모리 상황:
├─ 변수 a: 주소 0x1000, 값 0
├─ 포인터 p: 주소 0x2000, 값 0x1000 (a의 주소)
└─ *p = 100 실행 → 0x1000 주소(a)에 100 저장
Plain Text
복사
포인터 배열 vs 배열 포인터
포인터 배열 (Pointer Array)
// 포인터 배열
int a, b, c;
int* pArr[10] = { &a, &b, &c }; // 포인터를 담는 배열
C++
복사
배열 포인터 (Array Pointer)
// 배열 포인터
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
int (*pArr2)[10] = &arr; // 배열을 가리키는 포인터
C++
복사
•
int* pArr[10]: []가 우선순위 높음 → 포인터 배열
•
int (*pArr2)[10]: ()로 묶어서 포인터 먼저 → 배열 포인터
구조체 포인터와 -> 연산자
구조체, 클래스 타입의 변수도 결국 자료형이기 때문에 포인터 타입으로 선언이 가능하다.
#include <iostream>
struct Vector2
{
int x;
int y;
};
int main()
{
// 구조체 포인터 선언 목적
Vector2 p1;
Vector2* vp = &p1;
// 🔴 방법 1: (*포인터).멤버 - 번거로움
(*vp).x = 100;
(*vp).y = 100;
//*(vp.x) = 200; // ❌ 오류!
// 연산자가 역산자보다 우선순위가 높기 때문에
// 제대로 구조체 변수에 접근할 수 없다.
// ✅ 방법 2: -> 포인터 연산자 (깔끔!)
vp->x = 100;
vp->y = 100;
return 0;
}
C++
복사
•
(*vp).x = vp->x (같은 의미, 더 간단한 표현)
연결리스트 구현 예시
위에서 배운 내용을 활용하기 위해서 다음과 같이
구조체 포인터 변수와 같은 구조체의 주소를 저장할 수 있는 포인터타입을 선언하여 각 객체를 연결시켜 보자.
#include <iostream>
struct Node
{
int data; // 데이터 저장
Node* next; // 다음 노드를 가리키는 포인터
};
int main()
{
// 📝 종이 할 것이 대우 떡리해진다.
Node* head; // 첫 번째 노드를 가리키는 포인터
Node n1; // 첫 번째 노드
Node n2; // 두 번째 노드
Node n3; // 세 번째 노드
// 🔗 노드들을 연결
head = &n1; // head가 첫 번째 노드를 가리킴
n1.next = &n2; // 첫 번째 → 두 번째
n2.next = &n3; // 두 번째 → 세 번째
// 📊 데이터 저장
n1.data = 1;
n2.data = 2;
n3.data = 3;
// 🖨️ 연결된 데이터 출력
std::cout << head->data; // 1 출력
std::cout << head->next->data; // 2 출력
std::cout << head->next->next->data; // 3 출력
return 0;
}
C++
복사
head → [1|next] → [2|next] → [3|null]
↑ n1 ↑ n2 ↑ n3
head->data: 1
head->next->data: 2
head->next->next->data: 3
Plain Text
복사
•
포인터: 주소를 저장하는 변수 (int* p)
•
역참조: p로 포인터가 가리키는 값에 접근
•
구조체 포인터: > 연산자로 멤버에 간편하게 접근
•
연결리스트: 포인터로 노드들을 체인처럼 연결하는 자료구조
동적할당
•
정적 할당: 컴파일 시간에 메모리 크기 결정
•
동적 할당: 실행 시간에 메모리 크기 결정
•
메모리 해제: 프로그래머가 명시적으로 해제하거나 가비지 컬렉션 대상
“강의는 많은데, 왜 나는 아직도 코드를 못 짤까?”
혼자 공부하다 보면 누구나 이런 고민을 하게 됩니다.
•
강의는 다 들었지만 막상 손이 안 움직이고,
•
복습을 하려 해도 무엇을 다시 봐야 할지 모르겠고,
•
질문할 곳도 없고,
•
유튜브는 결국 정답을 따라 치는 것밖에 안 되는 것 같고.
문제는 ‘연습’이 빠졌기 때문입니다.
단순히 강의를 듣는 것만으로는 실력이 늘지 않습니다.
실제 문제를 풀고, 고민하고, 직접 구현해보는 시간이 반드시 필요합니다.
그래서, 얌얌코딩 코칭은 다릅니다.
그냥 가르치지 않습니다.
스스로 설계하고, 코딩할 수 있게 만듭니다.
얌얌코딩 코칭에서는 단순한 예제가 아닌,
스스로 문제를 분석하고 구현해야 하는 연습문제를 제공합니다.
이 연습문제들은 다음과 같은 역량을 키우기 위해 설계되어 있습니다:
•
문제를 스스로 쪼개고 설계하는 힘
•
다양한 조건을 만족시키는 실제 구현 능력
•
기능 단위가 아닌, 프로그램 단위로 사고하는 습관
•
마침내 자신의 힘으로 코드를 끝까지 작성하는 경험
지금 필요한 건 더 많은 강의가 아닙니다.
코드를 스스로 완성해 나가는 훈련,
그것이 지금 실력을 끌어올릴 가장 현실적인 방법입니다.