정보처리기사

[정처기] 03. C언어 배열, 포인터 +연습문제

gani00 2026. 6. 27. 17:16

목차

  • 배열
  • 포인터
  • 배열과 포인터
  • 2차원 배열과 포인터

배열은 값을 연속해서 저장하는 공간이고,
포인터는 그 공간의 주소를 저장하는 변수다.


1. 배열

배열은 같은 자료형의 값을 여러 개, 순서대로 저장하는 공간

int arr[3] = {10, 20, 30};
 

 


2. 포인터

포인터는 주소를 저장하는 변수

int num = 10;
int *p = #
 

 
포인터를 통해 실제 값을 바꿀 수도 있다.
*p = 50;


그러면 p가 가리키는 곳의 값이 바뀌므로,

printf("%d", num);  // 50
 

 


3. 배열과 포인터의 관계

int arr[3] = {10, 20, 30};
int *p = arr;
 
                    p
                    │
                    ▼
주소            200        204        208
              ┌────────┬────────┬────────┐
배열 arr      │ arr[0] │ arr[1] │ arr[2] │
              ├────────┼────────┼────────┤
저장된 값      │   10   │   20   │   30   │
              └────────┴────────┴────────┘
 

p = arr; 이므로, p는 배열의 첫 번째 원소 arr[0]의 주소를 저장한다.

arr      = 200          // 첫 번째 원소의 주소
&arr[0]  = 200          // 첫 번째 원소의 주소
p        = 200          // arr[0]을 가리키는 포인터

arr[0]   = 10           // 첫 번째 원소의 값
*p       = 10           // p가 가리키는 곳의 값
따라서

 

다음 원소로 이동하기

p       ──▶ arr[0] ──▶ 값 10
p + 1   ──▶ arr[1] ──▶ 값 20
p + 2   ──▶ arr[2] ──▶ 값 30

*(p + 0)   // 10
*(p + 1)   // 20
*(p + 2)   // 30
 
 
 

배열 방식으로 쓰면:

arr[0]     // 10
arr[1]     // 20
arr[2]     // 30
 

따라서

// 배열 == 포인터 표현 == 값
arr[0] == *(arr + 0) == *p
arr[1] == *(arr + 1) == *(p + 1)
arr[2] == *(arr + 2) == *(p + 2)
 

 


 
다음 원소로 이동하기
int arr[3] = {10, 20, 30};
int *p = arr;
 

p가 1000을 가리킨다고 하고, int가 4바이트라면,

p + 1
 

은 주소 1001이 아니라 다음 int 원소 위치인 1004를 가리킨다.

p      // arr[0]의 주소
p + 1  // arr[1]의 주소
p + 2  // arr[2]의 주소
 

포인터 연산은 자료형 크기를 고려해서 이동한다.

포인터 자료형 p+1 이 이동하는 크기
char *p 1바이트
int *p 보통 4바이트
double *p 보통 8바이트

4. 2차원 배열과 포인터

int arr[2][3] = {
    {1, 2, 3},
    {4, 5, 6}
};

int가 4바이트라고 가정하고, 주소를 편의상 이렇게 두자.

arr[0][0] : 200   arr[0][1] : 204   arr[0][2] : 208
arr[1][0] : 212   arr[1][1] : 216   arr[1][2] : 220
 

시각화하면:

arr
 │
 ▼
      0행                           1행
┌───────────────┬───────────────┐
│   arr[0]      │    arr[1]     │
│ ┌────┬────┬────┐ │ ┌────┬────┬────┐ │
│ │ 1  │ 2  │ 3  │ │ │ 4  │ 5  │ 6  │ │
│ └────┴────┴────┘ │ └────┴────┴────┘ │
└───────────────┴───────────────┘
  200  204  208      212  216  220

arr은 첫 번째 의 주소

1차원 배열에서는 arr이 첫 번째 원소의 주소처럼 쓰였는데,
2차원 배열에서는 arr이 첫 번째 의 주소처럼 쓰인다.

arr       == &arr[0]
arr[0]    == &arr[0][0]
arr[1]    == &arr[1][0]
 

즉,

  • arr : 0행 전체를 가리킴
  • arr[0] : 0행의 첫 번째 원소를 가리킴
  • arr[1] : 1행의 첫 번째 원소를 가리킴

arr + 1은 “다음 행”으로 이동

arr      ──▶ arr[0]
arr + 1  ──▶ arr[1]
 

즉,

arr + 1 == &arr[1]
 

여기서 주의할 점:

arr + 1은 다음 원소가 아니라, 다음 으로 이동한다.

 

왜냐하면 arr의 한 칸은 int[3], 즉 int 3개짜리 한 행이기 때문이다.

그래서 주소도

arr      : 200
arr + 1  : 212
 

처럼 12바이트(= 3 * 4)만큼 이동한다.


arr[i][j]는 포인터로도 표현 가능

2차원 배열에서는 아래 공식이 중요하다.

arr[i][j] == *(*(arr + i) + j)
 

예를 들어:

arr[0][0] == *(*(arr + 0) + 0)   // 1
arr[0][1] == *(*(arr + 0) + 1)   // 2
arr[1][2] == *(*(arr + 1) + 2)   // 6
 

연습문제

1.  

#include <stdio.h>

int main() {
    int arr[] = {10, 20, 30, 40};
    int *p = arr;

    printf("%d ", *p++);
    printf("%d ", *p);
    printf("%d", *(p + 1));

    return 0;
}

 

답 : 10 20 30

2.

#include <stdio.h>

void change(int *p) {
    *(p + 1) = *p + *(p + 2);
}

int main() {
    int arr[] = {2, 4, 6};

    change(arr);

    printf("%d %d %d", arr[0], arr[1], arr[2]);

    return 0;
}

 

 

답 : 3 12 9

3.

#include <stdio.h>

void change(int *p) {
    *(p + 1) = *p + *(p + 2);
}

int main() {
    int arr[] = {2, 4, 6};

    change(arr);

    printf("%d %d %d", arr[0], arr[1], arr[2]);

    return 0;
}

 

답 : 2 8 6

4.

#include <stdio.h>

int main() {
    int arr[2][3] = {
        {1, 2, 3},
        {4, 5, 6}
    };

    printf("%d %d %d",
           *(*(arr + 0) + 2),
           *(*(arr + 1) + 0),
           *(*(arr + 1) + 2));

    return 0;
}

 

답 : 3 4 6

5. 

#include <stdio.h>

int main() {
    int arr[2][3] = {
        {1, 2, 3},
        {4, 5, 6}
    };

    int (*p)[3] = arr;

    p[0][1] = p[1][0] + p[0][2];
    p++;

    printf("%d %d %d",
           arr[0][1],
           (*p)[0],
           *(*p + 2));

    return 0;
}

 

답 : 7 4 6