5[P4C] C언어 코딩 도장 : UNIT 35
이번에는 malloc 함수를 이용해 포인터에 원하는 만큼 메모리 공간을 할당받아 사용하는 방법을 알아보겠다.
malloc → 사용 → free 패턴으로 사용할 수 있다.
Unit 35.1 메모리 할당하기
메모리를 사용하려면 malloc 함수로 사용할 메모리 공간을 확보해야 한다(memory allocation).
이때 필요한 메모리 크기는 바이트 단위로 지정한다(메모리 할당, 해제 함수는 stdlib.h 헤더 파일에 선언되어 있다).
- 포인터 = malloc(크기);
#include <stdio.h>
#include <stdlib.h> // malloc, free 함수가 선언된 헤더 파일
int main()
{
int num1 = 20; // int형 변수 선언
int *numPtr1; // int형 포인터 선언
numPtr1 = &num1; // num1의 메모리 주소를 구하여 numPtr에 할당
int *numPtr2; // int형 포인터 선언
numPtr2 = malloc(sizeof(int)); // int의 크기 4바이트만큼 동적 메모리 할당
printf("%p\n", numPtr1); // 006BFA60: 변수 num1의 메모리 주소 출력
// 컴퓨터마다, 실행할 때마다 달라짐
printf("%p\n", numPtr2); // 009659F0: 새로 할당된 메모리의 주소 출력
// 컴퓨터마다, 실행할 때마다 달라짐
free(numPtr2); // 동적으로 할당한 메모리 해제
return 0;
}
메모리를 할당할 때는 malloc 함수를 사용하며 할당할 메모리 공간의 크기를 넣어주는데, 원하는 시점에 원하는 만큼 메모리를 할당할 수 있다고 하여 동적 메모리 할당(dynamic memory allocation)이라 부른다.
여기서 numPtr1에는 일반 변수의 메모리 주소를 할당했고, numPtr2에는 malloc 함수로 메모리를 할당했다.
같은 메모리 주소라도 내부적으로는 약간의 차이가 있다. 스택과 힙 두 가지인데 변수는 스택(stack)에 생성되며 malloc 함수는 힙(heap) 부분의 메모리를 사용한다.
스택과 힙의 큰 차이점은 메모리 해제다. 스택에 생성된 변수는 사용한 뒤 따로 처리를 해주지 않아도 되지만 malloc 함수를 사용하여 힙에서 할당한 메모리는 반드시 해제를 해주어야 한다. 다음과 같이 free 함수로 메모리를 해제한다.
- free(포인터);
35.2 메모리에 값 저장하기
#include <stdio.h>
#include <stdlib.h> // malloc, free 함수가 선언된 헤더 파일
int main()
{
int *numPtr; // int형 포인터 선언
numPtr = malloc(sizeof(int)); // int의 크기 4바이트만큼 동적 메모리 할당
*numPtr = 10; // 포인터를 역참조한 뒤 값 할당
printf("%d\n", *numPtr); // 10: 포인터를 역참조하여 메모리에 저장된 값 출력
free(numPtr); // 동적 메모리 해제
return 0;
}
malloc 함수로 할당한 메모리에 값을 저장할 때는 똑같이 *numPtr = 10;처럼 포인터를 역참조한 뒤 값을 저장하면 된다.마찬가지로 printf 함수로 값을 출력할 때도 포인터를 역참조하여 값을 가져오면 된다.
단, 메모리를 할당하고 사용한 뒤에는 반드시 free 함수로 해제를 해준다.
35.3 메모리 내용을 한꺼번에 설정하기
memset 함수를 사용하면 메모리의 내용을 원하는 크기만큼 특정값으로 설정할 수 있다. 이때 설정하는 크기는 바이트 단위이다.
- memset(포인터, 설정할값, 크기);
#include <stdio.h>
#include <stdlib.h> // malloc, free 함수가 선언된 헤더 파일
#include <string.h> // memset 함수가 선언된 헤더 파일
int main()
{
long long *numPtr = malloc(sizeof(long long)); // long long의 크기 8바이트만큼 동적 메모리 할당
memset(numPtr, 0x27, 8); // numPtr이 가리키는 메모리를 8바이트만큼 0x27로 설정
printf("0x%llx\n", *numPtr); // 0x2727272727272727: 27이 8개 들어가 있음
free(numPtr); // 동적으로 할당한 메모리 해제
return 0;
}
먼저 memset 함수를 사용하려면 string.h 또는 memory.h 헤더 파일을 포함해야 한다. 그리고 memset 함수에 포인터, 설정할 값, 설정할 크기를 넣으면 된다.
memset 함수는 주로 다음과 같이 설정할 값을 0으로 지정하여 메모리의 내용을 모두 0으로 만들 때 주로 사용한다.
memset(numPtr, 0, 8); // numPtr이 가리키는 메모리를 8바이트만큼 0으로 설정
memset 함수에 설정할 크기를 지정할 때 보통 숫자 대신 sizeof를 사용한다.
35.4 널 포인터 사용하기
#include <stdio.h>
int main()
{
int *numPtr1 = NULL; // 포인터에 NULL 저장
printf("%p\n", numPtr1); // 00000000
return 0;
}
NULL이 들어있는 포인터를 널 포인터(null pointer)라고 하며 아무것도 가리키지 않는 상태를 뜻한다. 따라서 역참조는 할 수 없다.
실무에서는 주로 포인터가 NULL인지 확인한 뒤 NULL이면 메모리를 할당하는 패턴을 주로 사용한다.
'Programming Languages > C' 카테고리의 다른 글
[P4C] C언어 코딩 도장 : UNIT 37 (0) | 2021.03.03 |
---|---|
[P4C] C언어 코딩 도장 : UNIT 36 (0) | 2021.03.03 |
[P4C] C언어 코딩 도장 : UNIT 34 (0) | 2021.03.03 |
[P4C] CodeUp 1099 : [기초-2차원배열] 성실한 개미 (0) | 2021.02.25 |
[P4C] CodeUp 1098 : [기초-2차원배열] 설탕과자 뽑기 (0) | 2021.02.25 |