[03] 배열과 포인터 (array and pointer)

포인터와 배열 응용하기

참고 문헌 (Ch38) : https://dojang.io/mod/page/view.php?id=316

생각의 시작

크기가 고정된 배열을 사용 => 크기가 변할 수 있는 배열을 어떻게 선언할 수 있는지에 대한 고민에서 출발하는 일!

C언어에서 배열을 선언: 고정 크기의 배열 선언

1
2
int numArr[10]
// 10 : 고정크기 => 10개의 요소를 가지는 배열

직관적으로 가변 길이 배열 선언해보기

1
2
3
4
5
6
7
8
9
10
11
12
13
#define _CRT_SECURE_NO_WARNING
#include <stdio.h>

int main()
{
int size;

scanf("%d", &size); // 배열의 크기를 입력받음

int numArr[size]; // GCC에서는 사용 가능, Visual Studio 2015에서는 컴파일 에러

return 0;
}

컴파일러마다 다르지만, VS2015의 경우 컴파일 에러가 발생한다고 한다
=> 동적으로 지정하기 위해서는 포인터를 선언하고, 메모리를 할당한 뒤 메모리를 배열처렁 사용해야한다!


포인터에 할당된 메모리를 배열처럼 사용하기

포인터를 배열처럼 사용하는 방법: 포인터에 malloc 함수로 메모리를 할당하여 사용하기!
malloc: dynamic memory allocation 방법. 메모리를 필요할 때 할당하여 사용, 다 쓴 메모리는 free를 통해 반드시 해제해줘야함!
malloc을 이용하기 위해서는 stdlib을 추가해줘야한다!

할당하는 방법: (자료형) (*포인터이름) = malloc(sizeof(자료형) * 크기);

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <stdio.h>
#include <stdlib.h> // malloc, free 함수가 선언된 헤더 파일

int main()
{
int *numPtr = malloc(sizeof(int) * 10); // int 10개 크기만큼 동적 메모리 할당

numPtr[0] = 10; // 배열처럼 인덱스로 접근하여 값 할당
numPtr[9] = 20; // 배열처럼 인덱스로 접근하여 값 할당

printf("%d\n", numPtr[0]); // 배열처럼 인덱스로 접근하여 값 출력
printf("%d\n", numPtr[9]); // 배열처럼 인덱스로 접근하여 값 출력

free(numPtr); // 동적으로 할당한 메모리 해제 => 해제하지 않으면 계속 잡혀있음

return 0;
}

입력한 크기만큼 메모리를 할당하여 배열처럼 사용하기

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include <stdio.h>
#include <stdlib.h> // malloc, free 함수가 선언된 헤더 파일

int main()
{
int size;

scanf("%d", &size);

int *numPtr = malloc(sizeof(int) * size); // (int 크기 * 입력받은 크기)만큼 동적 메모리 할당

for (int i = 0; i < size; i++) // 입력받은 크기만큼 반복
{
numPtr[i] = i; // 인덱스로 접근하여 값 할당
}

for (int i = 0; i < size; i++) // 입력받은 크기만큼 반복
{
printf("%d\n", numPtr[i]); // 인덱스로 접근하여 값 출력
}

free(numPtr); // 동적으로 할당한 메모리 해제

return 0;
}

포인터에 할당된 메모리를 2차원 배열처럼 사용하기

할당하는 방법: (자료형) (*포인터이름) = malloc(sizeof(자료형\) x 세로크기 를 이용하여 행 공간 메모리 할당 -> 행의 크기만큼 반복하면서 ((포인터)[i]) = malloc(sizeof(자료형) x 가로크기) 를 이용하여 열 공간 메모리 할당

해제하는 방법: 행 크기만큼 반복하면서 free(포인터[i]); 와 같이 열 공간 메모리 해제 -> free((포인터)); 로 행 공간 메모리 해제

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#include <stdio.h>
#include <stdlib.h> // malloc, free 함수가 선언된 헤더 파일

int main()
{
int **m = malloc(sizeof(int *) * 3); // 이중 포인터에 (int 포인터 크기 * 행 크기)만큼
// 동적 메모리 할당. 배열의 행

for (int i = 0; i < 3; i++) // 행 크기만큼 반복
{
m[i] = malloc(sizeof(int) * 4); // (int 크기 * 열 크기)만큼 동적 메모리 할당.
// 배열의 열
}

m[0][0] = 1; // 행 인덱스 0, 열 인덱스 0인 요소에 값 할당
m[2][0] = 5; // 행 인덱스 2, 열 인덱스 0인 요소에 값 할당
m[2][3] = 2; // 행 인덱스 2, 열 인덱스 3인 요소에 값 할당

printf("%d\n", m[0][0]); // 1: 행 인덱스 0, 열 인덱스 0인 요소의 값 출력
printf("%d\n", m[2][0]); // 5: 행 인덱스 2, 열 인덱스 0인 요소의 값 출력
printf("%d\n", m[2][3]); // 2: 행 인덱스 2, 열 인덱스 3인 요소의 값 출력

for (int i = 0; i < 3; i++) // 행 크기만큼 반복
{
free(m[i]); // 2차원 배열의 열 공간 메모리 해제
}

free(m); // 2차원 배열의 행 공간 메모리 해제

return 0;
}

입력한 크기만큼 메모리를 할당하여 포인터를 2차원 배열처럼 사용하기

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
#include <stdio.h>
#include <stdlib.h> // malloc, free 함수가 선언된 헤더 파일

int main()
{
int row, col;

scanf("%d %d", &row, &col);

// 2차원 배열 선언 시작
int **m = malloc(sizeof(int *) * row); // 이중 포인터에 (int 포인터 크기 * row)만큼
// 동적 메모리 할당. 배열의 행

for (int i = 0; i < row; i++) // 세로 크기만큼 반복
{
m[i] = malloc(sizeof(int) * col); // (int의 크기 * col)만큼 동적 메모리 할당. 배열의 열
}
// 2차원 배열 선언 끝

// 2차원 배열에 값 할당 시작
for (int i = 0; i < row; i++) // 행 크기만큼 반복
{
for (int j = 0; j < col; j++) // 열 크기만큼 반복
{
m[i][j] = i + j; // 2차원 배열의 각 요소에 i + j 값을 할당
}
}
// 2차원 배열에 값 할당 끝

for (int i = 0; i < row; i++) // 행 크기만큼 반복
{
for (int j = 0; j < col; j++) // 열 크기만큼 반복
{
printf("%d ", m[i][j]); // 2차원 배열의 인덱스에 반복문의 변수 i, j를 지정
}
printf("\n"); // 가로 요소를 출력한 뒤 다음 줄로 넘어감
}

// 2차원 배열 메모리 해제 시작
for (int i = 0; i < row; i++) // 행 크기만큼 반복
{
free(m[i]); // 2차원 배열의 열 공간 메모리 해제
}

free(m); // 2차원 배열의 행 공간 메모리 해제
// 2차원 배열 메모리 해제 끝

return 0;
}