

C의 malloc 함수는 대체 언제 어떻게 써야 하는 건지 알아봅시다.
int num; -> 4바이트 공간 확보!int arr[3]; -> 4바이트 * 3 = 12바이트 확보!malloc: 실행 중 메모리를 동적 할당memory allocation이라서 엠 얼록처럼 읽는다고 함free: 동적 할당한 메모리를 반환<stdlib.h> 헤더를 인클루드하고 사용해야 함#include <stdio.h>
#include <stdlib.h>
int main(void){
// 포인터를 선언만 하고 초기화하지 않음
int *pi;
double *pd;
// 4바이트 할당 후 포인터 연결
pi = (int *)malloc(sizeof(int));
// 동적할당에 실패하면 널 포인터 반환
if (pi == NULL){
printf("메모리가 부족합니다.\n");
exit(1);
}
// 8바이트 할당 후 포인터 연결
pd = (double *)malloc(sizeof(double));
*pi = 10;
*pd = 3.4;
printf("*pi: %d\n", *pi);
printf("*pd: %.1lf\n", *pd);
// 사용 후 영역 반환
free(pi);
free(pd);
return 0;
}
malloc - 공간 할당malloc(할당할 저장 공간의 크기)와 같이 사용(void *)형이므로, 용도에 맞는 포인터로 형 변환해야 함pi = (int *)malloc(sizeof(int))sizeof(int) -> 4바이트의 공간을 할당(int *)로 형변환해 (int *)형 포인터 pi에 대입int *pi = (int *)malloc(sizeof(int)) 처럼 초기화와 동시에 할당도 가능
🫤 지금까진 이렇게 안 하고 pi = &a로 주소를 대입했었잖아요! malloc은 왜 필요한 거에요?
p를 선언만 하고 초기화하지 않으면, 기본적으로 쓰레기 값을 가지고 있습니다. 즉 유효한 메모리 위치를 가리키지 않을 수 있습니다.pi = &a 식으로 기존 변수의 주소를 대입하면, a를 선언하면서 이미 할당된 메모리의 주소가 대입됩니다. 즉 malloc 없이 포인터를 사용할 수 있습니다.10, 3.4를 저장할 공간이 따로 존재하지 않습니다.malloc으로 메모리를 확보하고 그 주소를 포인터에 저장하는 겁니다.malloc은 요청한 크기의 공간 할당에 실패하면 NULL을 반환NULL은 전처리 단계에서 0으로 바뀜malloc이 반환한 NULL을 포인터에 대입하고 참조하면, Segmentation Fault 발생malloc이 NULL을 반환했는지 확인하고 사용해야 함if (pi == NULL) exit(1);와 같이 예외 처리 필요🫤 Segmentation Fault는 뭘 뜻하는 건가요?
int* pi;
*pi = 10; // 초기화되지 않은 포인터에 접근할 시
NULL 포인터에 접근하려고 할 시, 대부분 OS는 0번지 주소에 대한 접근을 차단하므로 곧바로 세그폴트를 때립니다.free - 공간 반환int a, int arr[4]와 같이 지역 변수를 선언하며 자동으로 할당된 메모리는, 함수가 종료되면 곧바로 해제됨free(포인터)를 이용해 직접 메모리를 회수해야 함int형 변수 5개를 저장해야 할 때int *pi = (int *)malloc(sizeof(int) * 5); // 4 * 5 = 20바이트 할당
int sum = 0; // 배열 값의 합을 저장할 변수
if (pi == NULL){
printf("메모리가 부족합니다\n");
exit(1);
}
printf("5개의 값을 입력하세요: ");
// 20바이트를 4바이트씩 끊어서, 5개의 int 변수 저장
for (int i = 0; i < 5; i++){
scanf("%d", pi + i); // 주소 값은 4바이트 크기만큼 증가
sum += *(pi + i); // *(pi + i) 말고 pi[i] 쓰셔도 됨
}
printf("평균값: %.1lf\n", (sum / 5.0));
free(pi); // 메모리 공간 반환
int 5개를 저장 -> 바이트 저장공간 할당pi + i 포인터 연산으로, 주소 값을 int형의 크기인 4만큼 증가시켜 사용⚠️ 이 경우 free를 할 때 무조건 한꺼번에 free(pi)를 해 줘야 합니다.
int 5개를 저장할 공간이 할당된 만큼 free(&pi[0]), free(&pi[1])... 이렇게 따로 해도 될 거라고 착각할 수 있지만free는 malloc 또는 관련 함수(calloc, realloc)로 받은 정확한 시작 주소만 받을 수 있습니다.free(&pi[0])은 어쨌든 pi와 같은 주소를 가지는 만큼 잘 작동된다 쳐도, free(&pi[1])부터 오류가 뜨거나 예기치 못한 동작이 발생할 수 있습니다. 그니까 하지 마요.calloc: 0으로 초기화
calloc: 메모리를 동적으로 할당한 뒤, 할당한 공간을 0으로 초기화calloc(배열 요소의 개수, 각 요소 하나의 크기)malloc과 다름에 유의.int형 변수 5개를 저장할 공간을 할당 시, malloc(sizeof(int) * 5)가 아닌 calloc(5, sizeof(int))와 같이 호출malloc과 마찬가지로 시작 위치를 void *로 반환, 형 변환해서 사용// 5개의 int를 저장할 공간 할당 후, 값을 0으로 초기화
int *pi = calloc(5, sizeof(int));
for (int i = 0; i < 5; i++){
printf("%4d", *(pi + i));
}
// 0 0 0 0 0
realloc: 저장공간 크기 조정
realloc: 이미 할당된 저장공간의 크기를 조절realloc(저장공간의 포인터, 조정 이후 저장공간의 크기)malloc과 마찬가지로 시작 위치를 void *로 반환, 형 변환해서 사용int count = 0; // 입력된 수의 개수
int num; // 수를 입력받을 변수
int size = 5; // 현재 저장공간에 저장할 수 있는 int 요소의 수
int *pi = malloc(size * sizeof(int)); // 일단 5개의 int 저장 가능
while (1){
printf("저장할 양수를 입력하세요: ");
scanf("%d", &num); // num에 수 입력받기
if (num <= 0) break; // 0 이하 값이면 종료
if (count == size){
size += 5; // 저장공간이 꽉 찬 경우 재할당
pi = (int *)realloc(pi, size * sizeof(int));
}
pi[count] = num;
count += 1;
}
for (int i = 0; i < count; i++){
printf("%3d", pi[i]);
}
free(pi); // 동적 할당된 공간 반환
// [출력]
// 저장할 양수를 입력하세요: 7
// 저장할 양수를 입력하세요: 6
// 저장할 양수를 입력하세요: 5
// 저장할 양수를 입력하세요: 4
// 저장할 양수를 입력하세요: 3
// 저장할 양수를 입력하세요: 2
// 저장할 양수를 입력하세요: 1
// 저장할 양수를 입력하세요: 0
// 7 6 5 4 3 2 1
int 변수 5개를 저장할 20바이트만 할당size로 현재 저장할 수 있는 최대 변수 수를 관리size를 5 증가시키고, size * sizeof(int) 만큼 메모리 재할당