포인터에 원하는 만큼 메모리 공간을 할당받아 사용하는 방법을 알아보자.
메모리는 malloc → 사용 → free 패턴으로 사용한다.
메모리 할당하기
메모리를 사용하려면 malloc 함수로 사용할 메모리 공간을 확보해야 한다.
(malloc : memory allocate)
이때 필요한 메모리 크기는 바이트 단위로 지정한다.
메모리 할당, 해제 함수는 stdlib.h 헤더 파일에 선언이 되어있다.
#include <stdio.h>
#include <stdlib.h>
int main()
{
int num1 = 20; // int형 변수 선언
int* numPtr1; // numPtr1 포인터 변수 선언
numPtr1 = &num1; // num1의 메모리 주소를 numPtr1에 할당
int* numPtr2; // numPtr2 포인터 변수 선언
numPtr2 = malloc(sizeof(int)); // numPtr2에 int형 사이즈만큼 동적 메모리 할당
printf("%p\n", numPtr1); // 변수 num1의 메모리 출력
printf("%p\n", numPtr2); // 포인터 변수 numPtr2에 새로 할당된 메모리 주소 출력
free(numPtr2); // 동적으로 할당된 메모리 해제
return 0;
}
메모리를 할당할때에는 malloc 함수를 사용하며 할당할 메모리 공간의 크기를 넣어준다.
여기서는 sizeof 연산자를 사용하여 int의 크기(4바이트)만큼 메모리를 할당했다.
특히 원하는 시점에 원하는 만큼 메모리를 할당할 수 있다고 하여 동적 메모리 할당(dynamic memory allocate)라고
부른다.
이때 numPtr1에는 일반 변수의 메모리 주소를 할당했고 numPtr2에는 malloc 함수로 메모리를 할당했다.
같은 메모리 주소라도 내부적으로는 약간의 차이가 있다.
변수는 스택(stack)에 생성되며, malloc 함수는 힙(heap) 부분의 메모리를 사용한다.
스택과 힙의 가장 큰 차이점은 메모리 해제이다. 스택에 생성된 변수는 사용한 뒤 따로 처리를 해주지 않아도 되지만
malloc 함수를 사용하여 힙에서 할당한 메모리는 반드시 해제를 해주어야 한다.
따라서 free 함수로 메모리를 해제해야 한다.
이때 메모리 해제는 선택이 아닌 필수이다. 실무에서는 메모리를 자주, 많이 할당하기에 메모리를 할당만 하고 해제를 해주지 않으면 결국에는 시스템의 메모리가 부족해지므로 운영체제가 프로그램을 강제로 종료시키거나 메모리 할당에 실패하게 된다.
특히 메모리를 해제하지 않아 메모리 사용량이 계속 증가하는 현상을 메모리 누수(memory leak)라 부른다.
메모리에 값 저장하기
malloc 함수로 할당한 메모리에 값을 저장할때는
*numPtr = 10; 처럼 포인터를 역참조한 뒤 값을 저장하면 된다.
마찬가지로 printf 함수로 값을 출력할 때도 포인터를 역참조하여 값을 가져오면 된다.
메모리를 할당하고 사용한 뒤에는 반드시! free 함수로 해제해주어야 한다!
메모리 내용을 한꺼번에 설정하기 (?이해가 잘 안가긴 함)
포인터를 역참조한 뒤 값을 할당할 때는 해당 자료형 크기만큼만 할당할 수 있다.
예를들어 int형은 4바이트니 malloc에서는 4바이트 만큼 할당이 가능하겠다.
memset 함수를 사용하면 메모리의 내용을 원하는 크기만큼 특정 값으로 설정할 수 있다.
(함수 명은 memory set에서 따왔다.) memset은 string.h 헤더 파일에 선언되어 있다.
설정하는 크기는 바이트 단위이다.
- memset(포인터, 설정할값, 크기);
널 포인터 사용하기
메모리가 할당되지 않은 포인터이다.
NULL이 들어있는 포인터를 널 포인터(null pointer)라고 하며 아무것도 가리키지 않은 상태를 뜻한다.
따라서 역참조는 할 수 없다.
실무에서는 포인터가 NULL인지 확인한 뒤 NULL이면 메모리를 할당하는 패턴을 주로 사용한다.
if (ptr == NULL)
{
ptr = malloc(1024);
}
심사문제: 두 정수의 합 구하기
아래는 정답이다.
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
int main()
{
int num1; // 변수 num1 생성
int num2; // 변수 num2 생성
int* numPtr1 = malloc(sizeof(int)); // 동적 메모리 할당
int* numPtr2 = malloc(sizeof(int)); // 동적 메모리 할당
scanf("%d %d", &num1, &num2);
*numPtr1 = num1; // 역참조 numPtr1의 값에 num1 정수값 할당
*numPtr2 = num2; // 역참조 numPtr2의 값에 num2 정수값 할당
printf("%d\n", *numPtr1 + *numPtr2); // 역참조 numPtr1 + 역참조 numPtr2
free(numPtr1); // 동적 메모리 해제
free(numPtr2); // 동적 메모리 해제
return 0;
}
'C, C++' 카테고리의 다른 글
C언어 코딩도장(배열: 가장 작은 수 출력하기) (0) | 2022.04.29 |
---|---|
C언어 코딩도장(배열 사용하기) / 2진수 계산기 (0) | 2022.04.29 |
C언어 코딩도장(포인터 사용하기) (0) | 2022.04.29 |
[C언어] 약수 구하기 (0) | 2022.04.28 |
[C언어] FizzBuzz / 삼항연산자 중첩 (2) | 2022.04.28 |