2021. 10. 30. 23:23ㆍDiary/300~400
저번에는 Stack에 대한
코드를 작성해보고 학습했다.
이제 아래의 이미지를 살펴보자.
또한, 아래의 사이트에서
설명을 읽어보자
( http://www.tcpschool.com/c/c_memory_structure )
이전에 Stack과 Heap에 대한 개념을
비유와 함께 어느정도 익혔다.
위의 내용을 전부 이해하지는 못하더라도
대충 느낌은 알 수 있을 것이다.
Heap 영역에 대한 설명을 보면
"힙 영역은 사용자가 직접 관리할 수 있는"
"그리고 관리를 해야만 하는 영역이다."
"힙 영역은 사용자에 의해 메모리 공간이"
"동적으로 할당되고 해제된다."
한 줄로 요약해보면,
"힙 영역은 사용자가 동적으로 관리하는 영역"
정도로 이해하면 될 것 같다.
힙(Heap) 정렬이라는 것도 있다.
이는 힙(Heap)이라는 데이터 구조를 사용해서
수열을 정렬하는 알고리즘이다.
대략적인 힙 알고리즘 설명을 해보자면,
1. Heap에 모든 숫자를 저장한다.
2. 이를 내림차순으로 구축한다.
3. Heap에 저장된 숫자를 하나씩 꺼낸다.
4. 내림차순 힙은 큰 것부터 순서대로 데이터를
추출하는 성질이 있으므로 꺼낸 숫자를 역순으로
나열하면 정렬이 완료된다.
일반적인 사용 방법을 짧게 설명하면,
수열이 저장 되어 있는 배열 자체에
힙(Heap)을 넣어서 배열상에서
숫자를 교체해가며 정렬한다.
힙(Heap)에 대해서 검색하면
힙 영역과 힙 정렬 이렇게 2개가
검색되기 때문에,
헷갈렸을 것 같아서 설명했다.
< 힙 영역 >
메모리에 데이터를 쌓을 수 있는 공간
< 힙 정렬 >
배열을 이진트리로 해석해 정렬하는 알고리즘
< Malloc & Free >
malloc의 사용법
void* malloc(size_t size)
size_t는 동적으로 할당할
메모리의 크기를 말한다.
성공 시, 할당한 메모리의
첫 번째 주소를 리턴해준다.
실패 시, NULL을 리턴한다.
free의 사용법
void free(void *ptr)
ptr은 해제하고자 하는
메모리의 포인터를 말한다.
동적에 대한 설명은 이전에 했으니
넘기도록 하겠다.
malloc와 free를 어떻게 사용해야 할까?
코드를 작성해 보기 전에
생각을 해보자.
사용자에게 선택지를 줘보자.
1. 배열 크기 지정
2. 배열에 숫자 넣기
3. 배열 출력
이렇게 하면 충분히 동적으로 보인다.
한번 코드를 작성해보자.
#include <stdio.h>
#include <stdlib.h>
// malloc 사용법
// => void* malloc(size_t size)
// size_t : 동적으로 할당할 메모리의 크기
// 성공시 할당한 메모리의 첫번째 주소 리턴, 실패시 NULL리턴
// free 사용법
// => void free(void *ptr);
// ptr : 해제하고자 하는 메모리의 포인터
void menu_print() {
printf("\n======================\n");
printf("0. 종료\n");
printf("1. 배열 크기 지정\n");
printf("2. 배열에 숫자 넣기\n");
printf("3. 배열 출력\n");
printf("======================\n");
printf("\n 선택 : ");
}
void main() {
int select;
int temp_memory_size;
int temp_memory_num = 0;
int *memory;
while(1) {
menu_print();
scanf("%d", &select);
if(select == 1) {
temp_memory_size = 0;
memory = 0;
temp_memory_num = 0;
printf("\n 배열 크기 지정 : ");
scanf("%d", &temp_memory_size);
// 메모리 동적 할당
memory = (int*)malloc(sizeof(int) * temp_memory_size);
}else if(select == 2) {
if(temp_memory_size <= temp_memory_num) {
printf("\n ! 배열이 가득 찼습니다 !\n");
} else {
printf("\n 배열에 숫자 넣기 : ");
scanf("%d", &memory[temp_memory_num]);
temp_memory_num++;
}
}else if(select == 3) {
printf("\n < 배열 출력 > \n");
for(int k = 0; k < temp_memory_size; k++) {
printf("%d\n", memory[k]);
}
}else if(select == 0) {
free(memory);
break;
}
}
}
malloc를 언제 자주 사용할지
생각해봤다.
내가 생각했을 때는,
배열 크기를 동적으로 할당할 때.
라고 생각한다.
메모리 누수를 막기 위해서는
위 처럼 Heap 영역을 제어해야한다.
다만, 내 경험이 아직 부족해서
메모리를 이렇게까지 최적화할 필요가
있는가에 대해서는 회의적이다.
IoT처럼 사양이 낮은 기기에서는
필요할 것 같다.
하지만, 일반적인 기기에서는 잘 모르겠다.
요즘 사양이 워낙 좋아져서..
물론, 최적화를 해서 나쁜건
전혀 없다고 생각한다.
하면 좋지.. 근데, 시간이 많이 걸리잖아..
지금은 위처럼 생각한다.
하지만 경력이 쌓이고 경험이 많아지면
최적화에 대한 필요성을
내 스스로가 느끼지 않을까 싶은 생각도 있다.
뭐든지 직접 느끼고 이해해야 와닿는다.
지금은 메모리 최적화에 대해서
필요성은 인지하고 있지만
최적화를 무조건 해야하냐고 물으면
그건 아니라고 답할 것 같다.
'Diary > 300~400' 카테고리의 다른 글
307일차 - 가독성과 안전한 코드, also, with, let, run, apply, Room (0) | 2021.11.01 |
---|---|
306일차 - 간단한 조사(AI, DL 설명 및 사용 기술) (0) | 2021.10.31 |
304일차 - Kotlin Room을 활용한 간단한 게시판 만들기 (1) | 2021.10.29 |
303일차 - Android Room 정리 (0) | 2021.10.28 |
302일차 - 계획 수립 및 Android Room, 인공지능(AI), 딥러닝(DL) (0) | 2021.10.27 |