티스토리 뷰

728x90
SMALL

프로그램을 실행하면 해당 프로그램의 실행을 위한 메모리 공간이 운영체제에 의해서 미리 마련이 된다.

그리고 바로 이 메모리 공간 내에서 변수가 선언되고, 문자열이 선언되는 것이다.

 

운영체제에 의해 할당된 메모리의 구조

코드 영역, 데이터 영역, 힙 영역, 스택 영역

 

코드 영역

실행할 프로그램의 코드가 저장되는 메모리 공간. 따라서 CPU는 코드 영역에 저장된 명령문들을 하나씩 가져가서 실행

데이터 영역

전역변수와 static으로 선언되는 static 변수가 할당된다. 즉 프로그램의 시작과 동시에 메모리 공간에 할당되어 프로그램 종료 시까지 남아있게 된다.

스택 영역

지역변수와 매개변수가 할당된다. 이 영역에 할당된 변수들은 선언된 함수를 빠져나가면 소멸된다.

힙 영역

프로그램을 구현하다 보면, 이 데이터, 스택 영역의 변수들과는 다른 성격의 변수가 필요하다.  그래서 C언어에서는 프로그래머가 원하는 시점에 변수를 할당하고 또 소멸하도록 지원을 한다. 이러한 유형의 변수들이 할당되는 영역이 힙 영역

 

힙 영역의 메모리 공간 할당과 해제 : malloc과 free 함수

#include <stdlib.h>

void * malloc(size_t size); // 힙 영역으로의 메모리 공간 할당

void free(void * ptr); // 힙 영역에 할당된 메모리 공간 해제

  => malloc 함수는 성공 시 할당된 메모리의 주소 값, 실패 시 NULL 반환

 

힙에 할당된 메모리 공간은 포인터 변수를 이용해서 접근하는 방법밖에 없나요? 응

 

malloc 함수의 반한형은 void이므로 반환 값에 아무런 가공을 하지 않으면 할당된 메모리 공간에 접근불가

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
	int* ptr1 = (int*)malloc(sizeof(int));
	int* ptr2 = (int*)malloc(sizeof(int) * 7);
	int i;

	*ptr1 = 20;
	for (i = 0; i < 7; i++)
		ptr2[i] = i + 1;

	printf("%d \n", *ptr1);
	for (i = 0; i < 7; i++)
		printf("%d ", ptr2[i]);

	free(ptr1);
	free(ptr2);
	return 0;
}

 

#include <stdio.h>
#include <stdlib.h>

char* ReadUserName(void)
{
	char* name = (char*)malloc(sizeof(char) * 30);
	printf("What's your name? ");
	gets(name);
	return name;
}

int main(void)
{
	char* name1;
	char* name2;
	name1 = ReadUserName();
	printf("name1: %s \n", name1);
	name2 = ReadUserName();
	printf("name2: %s \n", name2);

	printf("again name1: %s \n", name1);
	printf("again name2: %s \n", name2);
	free(name1);
	free(name2);
	return 0;
}

malloc 함수의 사촌 뻘 되는 calloc 함수

#include <stdlib.h>

void * calloc(size_t elt_count, size_t elt_size);

  => 성공 시 할당된 메모리의 주소 값, 실패 시 NULL 반환

 

malloc 총 120바이트르르 힙 영역에 할당

calloc 4바이트 크기의 블록(elt_size) 30개를(elt_count) 할당

malloc 함수는 할당된 메모리 공간을 별도의 값으로 초기화 하지 않는다. 따라서 할당된 메모리 공간이 쓰레기 값

calloc 함수는 할당된 메모리 공간의 모든 비트를 0으로 초기화

 

힙에 할당된 메모리 공간 확장 시 호출하는 realloc 함수

한번 할당된 메모리 공간은 그 크기를 확장할 수 없지만, 힙이라면 realloc 함수를 사용해서 가능

#include <stdlib.h>

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

  => 성공 시 새로 할당된 메모리의 주소 값, 실패 시 NULL 반환

 

int main(void){
    int * arr = (int *)malloc(sizeof(int)*3);  // 길이가 3인 int형 배열 할당
    arr = (int *)realloc(arr, sizeof(int)*5);  // 길이가 5인 int형 배열로 확장
    ...
}

위 코드의 실행결과는 반환 값을 기준으로 다음과 같이 두가지로 구분이 된다.

malloc 함수가 반환한 주소 값과 realloc 함수가 반환한 주소 값이 같은 경우

malloc 함수가 반환한 주소 값과 realloc 함수가 반환한 주소 값이 같지 않을 경우

전자는 확장할 영역이 넉넉한 경우

넉넉하지 않은 경우에는 힙의 다른 위치에, 새로이 요구하는 크기의 메모리 공갼을 별도로 할당해서 이전 배열에 저장된 값을 복사하기도 한다. 이런 경우 malloc, realloc의 반환 값이 같지 않다.

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main(void)
{
	int maxlen, len, i;
	char* str;

	printf("문자열의 최대길이 입력 : ");
	scanf_s("%d", &maxlen);
	getchar();
	str = (char*)malloc(sizeof(char) * (maxlen + 1));
	
	printf("문자열 입력 : ");
	fgets(str, maxlen + 1, stdin);
	str[strlen(str) - 1] = 0;
	len = strlen(str);
	for (i = len; i > 0; i--) {
		if(str[i]==' '){
			printf("%s ", &str[i + 1]);
			str[i] = 0;
		}
	}
	printf("%s", &str[0]);
	free(str);
	return 0;
}
#include <stdio.h>
#include <stdlib.h>

int main(void)
{
	int arrlen = 5;
	int idx = 0;
	int i;
	int* arr = (int*)malloc(sizeof(int) * arrlen);
	while(1){
		printf("정수를 입력 : ");
		scanf_s("%d", &arr[idx]);
		if (arr[idx] == -1) break;
		if (arrlen == idx + 1) {
			arrlen += 3;
			arr = (int*)realloc(arr, sizeof(int) * arrlen);
		}
		idx++;
	}
	for (i = 0; i < idx; i++)
		printf("%d", arr[i]);
	free(arr);
	return 0;
}
728x90
LIST

' > 윤성우 열혈 C 프로그래밍' 카테고리의 다른 글

파일의 분할과 헤더파일의 디자인  (0) 2020.09.26
메크로와 선행처리기  (0) 2020.09.25
파일 입출력2  (0) 2020.09.24
파일 입출력1  (0) 2020.09.23
구조체와 사용자 정의 자료형2  (0) 2020.09.21
댓글
공지사항