본문 바로가기
  • 시간(時間)을 아끼는 방법은 시간을 낭비하지 않는것


C_ language/C언어 심화_모각코

C언어_심화_동적 메모리 할당

by pk7912 2022. 6. 17.
728x90

커뮤니티_모각코 (모여서, 각자, 코딩) 활동을 하면서 배운 내용을 되새기며 쓴 글입니다.
코딩을 배우고 싶다면 코뮤니티 활동을 적극 추천합니다.

https://cafe.naver.com/codeuniv

 

코딩 커뮤니티 - 코뮤니티 [파이썬/... : 네이버 카페

코뮤니티 [코딩공부/독학/스터디/대외활동] : python, C언어, java, 자바스크립트, HTML, CSS, 웹/앱개발

cafe.naver.com

 

 


메모리

 

메모리의 구조부터 알아야 동적할당을 이해할 수 있습니다.

 

1. 코드 영역

함수와 상수, 실행할 프로그램의 코드가 저장되는 영역, 텍스트 영역이라고도 합니다.

컴파일 단계에서 검사를 마치고 저장되므로 정적 메모리 할당합니다.

 

 

2. 데이터 영역

전역 변수, 정적 변수, 구조체 등 함수 외부에서 선언되는 변수들이 할당되는 영역

프로그램의 시작과 함께 할당되며, 프로그램 종료 시까지만 남아있습니다.

코드 영역과 마찬가지로 컴파일 단계에서 검사를 마치고 저장되므로 정적 메모리 할당합니다.

 

3. 스택(stack) 영역

지역 변수와 매개 변수가 할당되는 영역, 컴파일 시점에 결정되는 영역

메인 함수안의 변수는 모두 스택 영역에 할당된 겁니다.

함수의 호출 시 할당되며, 함수가 완료되면 할당된 메모리를 반환합니다.

스택 영역은 push로 데이터를 저장하고, pop로 데이터를 인출합니다.

스택은 후입 선출 방식에 따라 동작합니다. 즉 , 마지막 데이터가 먼저 인출됩니다.

메모리의 높은 주소에서 낮은 주소 방향으로 할당됩니다.

 

4. 힙(heap) 영역

사용자가 직접 관리하는 동적 할당된 메모리들이 존재하는 공간

힙 영역은 메모리의 낮은 주소에서 높은 주소 방향으로 할당됩니다.

 

뭔가 헷갈리게 설명이 되어있는 거 같아서...

좀 더 알아보니 

메모리에서 동적, 정적 할당을 구분하는 것과 변수들의 동적, 정적 할당을 구분하는 것은 다르다고 합니다.

지역변수나 매개 변수는 컴파일 단계에서 공간을 할당받으니깐 정적 할당인데, 정작 할당받는 메모리 공간은 

동적 영역인  스택 영역입니다.

컴파일 단계에서 공간을 할당받으니 실행단계에서는 공간의 크기를 조절할 수 없지만,

스택 영역은 동적 영역이기 때문에 실행 중 얼마든지 해제할 수 있습니다.

 

정적 메모리 할당과 동적 메모리 할당에 대해 자세히 알아보겠습니다.


메모리 할당하는 방법

 

메모리 할당하는 방법에는  정적 메모리 할당과 , 동적 메모리 할당이 있습니다.

정적(static), 동적(dynamic) 할당을 구분하는 기준은 메모리 할당하는 시점입니다.

 

 

정적(static) 메모리 할당

     정적 메모리 할당은 컴파일 단계에서  메모리 공간을 할당합니다.

     보통 변수 선언을 통해 필요한 메모리를 확보하는 방법입니다.

      

정적 할당 예)

#pragma warning(disable : 4996)
#include <stdio.h>
#include <string.h>

int sum(int a, int b); // 매개변수 a, b

int main(void)
{
	int num1 = 3;	
	int num2 = 4;		// 지역변수 num1, num2
	static num3 = 5;	// 정적변수 num3

	printf("%d\n", sum(num1, num2));


	system("pause");
	return 0;
}

int sum(int a, int b)
{
	return a + b;
}

 

컴파일될때 메모리 공간

정적 할당은 컴파일해서 메모리를 할당받은 뒤 운영체제가 알아서 메모리 공간을 회수해 가기 때문에

메모리 누수를  걱정 안 해도 됩니다.

하지만 메모리 공간을 미리 정해놓기에 메모리가 모자랄 때 수정할 수 없고,  

혹시나 너무 크게 잡아 버리면 메모리 공간 낭비가 발생해 버립니다.

상황에 맞게 주의해서 사용해야 합니다.

 

 


 

동적 메모리 할당

 

동적(dynamic) 메모리 할당

동적 메모리 할당은 실행 단계에서 메모리 공간을 할당받습니다.

포인터를 사용하고, 포인터로 heap영역을 가리켜 해당 공간을 할당합니다.

#include <stdlib.h> 안에있는 //mallc(), free() 명령어 사용

동적 할당 예)

#pragma warning(disable : 4996)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void ex(int* k);

int main()
{
	int* num; 

	num = (int*)malloc(sizeof(int));

	*num = 10;

	ex(num);

	printf("동적할당 예 : %d\n", *num);

	free(num);

	printf("동적할당 예 : %d\n", *num);



	system("pause");
	return 0;
}

void ex(int* k)
{
	printf("%d\n", *k);
}

동적할당 컴파일시 메모리 공간

 

동적 할당은 직접 free() 함수로 메모리 공간을 반납합니다.

메모리 누수를 걱정해야 합니다.

하지만 동적 할당에서는 낭비되는 메모리나 모자란 메모리는 없습니다.

필요한 만큼 사이즈를 계산해서 공간을 주기에 낭비될 일이 없습니다.

 

동적 할당 함수에는 

malloc 이외에도 calloc() 함수와 realloc() 함수가 있습니다.

calloc() 함수는 메모리 공간을 확보하면서 초기값을 0으로 저장합니다.

calloc() 함수 원형은 

void * colloc(size_t n, size_t byte);

해석) byte 사이즈 크기의 변수를 n개만큼 저장할 수 있는 메모리 공간을 할당

calloc() 함수에서 앞의 인자는 배열의 개수이고, 뒤의 인자는 배열 한 원소의 크기입니다.

 

#pragma warning(disable : 4996)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(void)
{
	int* arr;

	// arr = (int *)malloc(sizeof(int) * 5);
	arr = (int*)calloc(5, sizeof(int));

	for (int i = 0; i < 5; i++)
	{
		arr[i] = i;
		printf("%d\n", arr[i]);
	}

	free(arr);

	system("pause");
	return 0;
}

 

realloc() 함수는 이미 할당된 공간의 크기를 바꿀 때 사용합니다.

기존 영역을 이용하여 변경하는 게 원칙이지만, 새로운 영역을 다시 할당하여 이전의 값을 복사할 수도 있습니다.

 

realloc() 함수 원형은 

void * realloc(void * mem, size_t size);

해석) 이미 할당한 포인터 변수를 mem에 , 바꾸려는 메모리 크기를 size에 입력

 

#pragma warning(disable : 4996)
#include <stdio.h>
#include <stdlib.h>
#include <string.h> 

int main(void)
{
	int* arr;
	
	//arr = (int*)malloc(sizeof(int) * 3);
	arr = (int*)calloc(3, sizeof(int));

	for (int i = 0; i < 3; i++)
	{
		arr[i] = i;
		printf("%d\n", arr[i]);
	}
	printf("\n");

	realloc(arr, sizeof(int) * 5); // 메모리 크기 변경!

	for (int i = 0; i < 5; i++)
	{
		arr[i] = i + 10;
		printf("%d\n", arr[i]);
	}
	free(arr);
}


 

practice

 

평균 점수 구하기

 

학생의 수를 입력받고, 그 수만큼 학생의 점수를 입력받아 평균을 구하시오.

 

#pragma warning(disable : 4996)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main() {
	int num;
	int* arr;
	int sum = 0;
	int avg;

	printf("학생의 수 : ");
	scanf_s("%d", &num);
	printf("\n");

	arr = (int*)malloc(sizeof(int) * num);

	for (int i = 0; i < num; i++)
	{
		printf("학생%d : ", i + 1);
		scanf_s("%d", &arr[i]);
		sum += arr[i];
	}

	free(arr);

	avg = sum / num;
	printf("\n평균 : %d\n", avg);

	system("pause");
	return 0;
}

 


 

마무리

문제를 표현하기가 어려웠습니다.

학생 수를 입력받고 입력받은 수만큼 점수를 입력해야 하고.... 그걸 평균 낸다....

어느 정도 이해는 했지만 몇 번 더 복습해야겠습니다.

이런 조건을 코딩으로 표현해보는 걸 익히다 보면

혼자 생각만 하던걸 코딩으로 구현할 수 있을 것 같습니다.

 

 

 

 

 

 

 

 

 

 

 

 

댓글