포인터와 malloc을 이용하면 run-time때 배열의 크기를 정할 수 있습니다. 상수로 배열의 크기를 정할 경우, int arr[10]; 이같이 배열 선언을 하고 arr[0] = 1; arr[1] = 2; arr[2] = 3; ... arr[9] = 10; 이렇게 값을 대입시키거나 scanf(“%d”, &arr[0]); 이런식으로 사용자로부터 값을 입력받게 됩니다. 반면, 포인터와 malloc을 이용하면, (malloc이란 memory allocation을 줄인말로 입력받은 길이(byte)만큼 메모리공간을 할당하는 함수입니다. malloc(4)이란 4 bytes 만큼 메모리공간을 할당하란 뜻입니다. 기본적으로 (void *) 리턴타입을 가지고있기 때문에 포인터에 대입 시 (int *) 또는 (char *) 이런식으로 Type Casting 을 하셔야합니다. 아래에 malloc 쓰인 곳을 보시면 이해가 가실겁니다.) #include <stdio.h> #include <malloc.h> // malloc함수가 정의되 있는 파일을 불러옵니다. int main() { int *arr; // 이런식으로 포인터변수를 선언하구요. int size; // 사용자로부터 입력받을 배열의 크기 int i; printf(“배열의 크기 입력: “); // 사용자로부터 배열의 크기 입력받음 scanf(“%d”, &size); arr = (int *)malloc(sizeof(int) * size); // 입력받은 크기만큼 int 배열을 형성합니다. 정확히 말하면, 배열을 형성한다기보단 입력받은 만큼의 메모리공간을 할당하는 것이죠. 이렇게해서 형성된 arr 포인터변수는 배열을 사용하는 것처럼 같은 방법으로 값을 입력하거나 값을 가져올 수 있습니다. printf(“값 입력\n”); for (i = 0; i < size; i++) { printf(“arr[%d]: “, i); scanf(“%d”, &arr[i]); } printf(“입력한 배열의 값 출력\n”); for (i = 0; i < size; i++) { printf(“arr[%d]: %d\n“, i, arr[i]); } return 0; } 포인터를 배열처럼 사용하는 방법은 간단합니다. 포인터에 malloc 함수로 메모리를 할당해주면 됩니다. 다음 내용을 소스 코드 편집 창에 입력하세요.
pointer_like_array.c #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; } 실행 결과 10 20 int *numPtr = malloc(sizeof(int) * 10);과 같이 int 크기에 10을 곱하여 동적으로 메모리를 할당합니다(sizeof(int)를 곱하지 않으면 배열처럼 사용할 수 없습니다). 그리고 배열처럼 [ ] 안에 인덱스를 지정하여 값을 할당하거나 가져올 수 있습니다. 즉, 배열과 메모리가 할당된 포인터는 생성 방법만 다를 뿐 값을 다루는 방법은 같습니다.
int numArr[10]; // int형 요소 10개를 가진 배열 생성 int *numPtr = malloc(sizeof(int) * 10); // int 10개 크기만큼 메모리 할당 numArr[0] = 10; // 배열을 인덱스로 접근하여 값 할당 numPtr[0] = 10; // 포인터를 인덱스로 접근하여 값 할당 free(numPtr); // 메모리 해제 단, 배열 numArr은 한 번 선언하면 끝이지만 포인터 numPtr은 malloc 함수로 메모리를 할당했기 때문에 free함수로 해제해줍니다. *numPtr처럼 포인터를 역참조한 것과 numPtr[0] 인덱스 0에 접근한 것은 같은 값을 가져옵니다. 그리고 numPtr[1] 과 *(numPtr + 1)도 같은 값을 가져오는데 *(numPtr + 1)와 같이 포인터에 값을 더하는 방식을 포인터 연산이라고 하며 'Unit 59 포인터 연산 사용하기'에서 자세히 설명하겠습니다. ▼ 그림 38‑1 포인터를 배열처럼 사용 |