정보처리기사
[정보처리기사 실기] 포인터 배열
@leem
2025. 4. 14. 19:47
1. 포인터 기본 개념
표현 | 의미 | 예시 | 해석 |
int *p | 정수형 포인터 변수 | int *p = &a; | a의 주소를 저장하는 변수 |
&변수 | 변수의 주소값 | &a[0] → 100 | |
*포인터 | 해당 주소에 있는 값 | *p → 주소 p가 가리키는 곳의 값 |
2. 배열과 포인터 관계
int a[3] = {10, 20, 30};
int *p = a; // == &a[0]
표현 | 해석 |
p[0] or *p | a[0] → 10 |
p[1] or *(p + 1) | a[1] → 20 |
p[2] or *(p + 2) | a[2] → 30 |
- p는 배열의 첫 번째 요소를 가리키고 있으므로, p[0] 또는 *p는 a[0]과 동일
- p[1] 또는 *(p + 1)은 a[1]과 동일하고, p[2]는 a[2]를 가리
📌 즉, 배열처럼 쓰면 된다. 주소 계산은 자동으로 처리됨!
3. 주소값과 값 구분
- p는 포인터가 가리키는 주소값을, *p는 해당 주소에 저장된 값을 참조
- p + 1은 주소를 1 증가시킨 것을 의미하고, *(p + 1)은 그 주소에 저장된 값을 가져옴
표현 | 뜻 | 예시 |
p | 주소값 | p = 103 |
*p | 그 주소의 값 | *p = -10 |
p + 1 | 다음 주소 | 주소가 1 증가 |
*(p + 1) | 다음 주소에 있는 값 | 예: *(104) |
예제에서는 주소값이 100부터 시작해 1씩 증가한다고 가정
예제 1 – 1차원 배열과 포인터
int a[3] = {-3, 14, 5};
int *p = &a[1];
printf("%d, ", a[1]);
printf("%d, ", p[1]);
🔍 풀이
주소 | 값 |
100 | -3 |
101 | 14 |
102 | 5 |
- a[1] = 14 이므로 p = &a[1]이면 p는 a[1]의 주소인 101번지를 가리킴.
- p = &a[1] = 101
a[1] 배열의 두 번째 요소 (14) &a[1] a[1]의 주소값 (101번지) p 주소값을 저장하는 포인터 변수 *p p가 가리키는 주소의 값 → 14 - p[1] = *(p + 1) = *(102) = 5
- p는 &a[1], 즉 배열 a의 두 번째 요소(14)의 주소인 101번지를 저장함
- 포인터 p를 기준으로 보면 p[0] = *p = *(101) = 14
- 그러면 p[1]은 *(p + 1) = *(101 + 1) = *(102) → 값 5
- p가 배열의 중간(a[1])부터 시작하는 새 배열처럼 동작하는 것
✅ 출력 결과: 14, 5
예제 2 – 2차원 배열을 1차원처럼
int a[2][3] = {{-3,14,5}, {1,-10,8}};
int *p = a[1];
printf("%d,", a[1][1]);
printf("%d,", p[1]);
🔍 풀이
주소 | 값 | 설명 |
100 | -3 | a[0][0] |
101 | 14 | a[0][1] |
102 | 5 | a[0][2] |
103 | 1 | a[1][0] |
104 | -10 | a[1][1] |
105 | 8 | a[1][2] |
- a[1]은 2차원 배열에서 두 번째 행: {1, -10, 8}
- int *p = a[1]; → p는 a[1][0]의 주소인 103번지를 저장
- 즉, p는 배열 {1, -10, 8}의 첫 요소를 가리키는 포인터가 된 것!
📌 그럼 각 요소는?
표현 | 의미 | 값 |
p[0] | *(p + 0) = *(103) | 1 |
p[1] | *(p + 1) = *(104) | -10 |
p[2] | *(p + 2) = *(105) | 8 |
p는 a[1]의 시작 주소를 가리키기 때문에, p[1]은 a[1][1]과 같은 위치인 104번지의 값을 의미하며 그 결과는 -10이다.
- a[1][1] = -10
- p = a[1] = &a[1][0] = 103
- p[1] = *(p + 1) = *(104) = -10
✅ 출력 결과: -10, -10
예제 3 – 포인터 배열과 이동
int a[2][3] = {{-3,14,5}, {1,-10,8}};
int *b[] = {a[0], a[1]};
int *p = b[1];
printf("%d, ", *b[1]);
printf("%d, ", *(++p));
printf("%d", *(--p - 2));
🔍 풀이
주소 | 값 | 설명 |
100 | -3 | a[0][0] |
101 | 14 | a[0][1] |
102 | 5 | a[0][2] |
103 | 1 | a[1][0] |
104 | -10 | a[1][1] |
105 | 8 | a[1][2] |
- int *b[] = {a[0], a[1]};
b는 포인터 배열: 각각의 요소가 주소(포인터) 를 담고 있음 ✨값이 들어간 게 아님!
b[0] = a[0] 첫 번째 행 시작 주소 100번지
b[1] = a[1] 두 번째 행 시작 주소 103번지
→ 즉, b[1]은 배열 a[1]을 가리킴 - int *p = b[1];
→ p는 a[1][0] = 1의 주소인 103번지 - *b[1] ✨ *이 붙으면 그 주소에 저장된 "값"을 꺼냄 (103번지에 저장된 값)
→ *103 = a[1][0] = 1 - *(++p)
→ ++p는 p를 103번지에서 104번지로 이동 → a[1][1]
→ *p = *104 = -10 - *(--p - 2)
→ --p로 p를 한 칸 되돌려서 다시 103번지
→ p - 2 = 101번지
→ *101 = a[0][1] = 14
- *b[1] = *103 = 1
- ++p → p = 104 → *(p) = -10
- --p → p = 103, p - 2 = 101 → *(101) = 14
✅ 출력 결과: 1, -10, 14
마무리
- 포인터는 배열처럼 생각하면 된다.
- *p, p[n], *(p + n) → 전부 같은 의미
- 주소 이동을 상상하면 추적이 쉬워진다