티스토리 뷰
저자는 메모리 동적 할당 및 해제를 "어른스러운 혹은 자유에 대한 책임이 따르는 메모리 사용방법"이라고 비유합니다.
malloc() 함수와 free()함수를 소개하겠습니다.
이 함수들을 호출하기 위해서는 헤더에 #include<stdlib.h>를 포함해야합니다.
malloc() 함수는 인수로 전달받은 정수만큼의 바이트 단위 메모리를 동적으로 할당하고 주소를 반환합니다. 이 주소는 할당받은 메모리 전체에 대한 기준주소입니다. 따라서 이 주소를 기준으로 나머지에 접근할 수 있습니다.
그리고 사용이 끝난 다음에는 반드시 free() 함수를 이용해 메모리를 운영체제에 반환해야합니다.
void *malloc(size_t size); | ||
인자 | size | 할당받을 메모리의 바이트 단위 크기 |
반환값 |
힙 영역에 할당된 메모리 덩어리 중 첫 번째 바이트 메모리의 주소 에러가 발생하면 NULL 반환 |
|
설명 | 할당받은 메모리는 반드시 free() 함수를 이용하여 반환해야 하며, 메모리를 초기화하려면 memset() 함수를 이용해야합니다. 기본적으로는 쓰레기 값이 들어 있습니다. |
void free(void *memblock); |
||
인자 | memblock | 반환할 메모리의 주소 |
반환값 | 없음 |
|
설명 | 동적으로 할당받은 메모리를 운영체제에 반환하는 함수 |
#include<stdio.h>
#include<stdlib.h>
int main(void) {
int* pList = NULL, i = 0;
//12바이트(sizeof(int) * 3) 메모리를 동적 할당하고 시작주소를 pList 포인터 변수에 저장.
pList = (int*)malloc(sizeof(int) * 3);
//동적 할당한 대상 메모리를 배열 연산자로 접근한다.
pList[0] = 10; // *(pList + 0) = 10;
pList[1] = 20; // *(pList + 1) = 20; 과 같은코드도 똑같이 작동
pList[2] = 30;
for (i = 0; i < 3; i++)
printf("%d\n", pList[i]);
//동적 할당한 메모리를 해제한다.
free(pList);
return 0;
}
메모리 초기화 및 사용(배열)
변수를 선언하면 즉시 0으로 초기화하는 것이 일반적입니다. 그러므로 할당된 메모리는 일단 0으로 초기화하는 것이 바람직합니다.
동적 할당된 메모리를 초기화하는 두 가지 방법을 교재에서는 소개하고 있습니다.
#include<stdio.h>
//malloc(), calloc() 함수를 위한 헤더 포함
#include<stdlib.h>
//memset() 함수를 위한 헤더 포함
#include<string.h>
int main(void) {
int* pList = NULL, * pNewList = NULL;
//A. int형 3개 배열 선언 및 정의(0 초기화)
int aList[3] = { 0 };
//B. int형 3개를 담을 수 있는 크기의 메모리를 동적으로 '할당한 후 메모리를 모두 0으로 초기화'
pList = (int*)malloc(sizeof(int) * 3);
memset(pList, 0, sizeof(int) * 3);
//C. int형 3개를 담을 수 있는 메모리를 0으로 '초기화한 후 할당'받음
pNewList = (int*)calloc(3, sizeof(int));
//동적 할당한 메모리들을 해제
free(pList);
free(pNewList);
return 0;
}
여기에서 쓰인 memset()함수와 calloc()함수에 대해 알아보겠습니다.
void *memset(void *des, int c , size_t count); | |||
인자 |
dest |
초기화할 대상 메모리 주소 |
|
c |
초깃값, 이 값이 0이면 메모리를 0으로 초기화 |
||
count |
초기화 대상 메모리의 바이트 단위 크기 |
||
반환값 | 대상 메모리 주소 | ||
설명 | 동적으로 할당받은 메모리에는 쓰레기 값이 있으므로 일반적으로 0으로 초기화하여 사용한다. |
void *calloc(size_t num, size_t size); | |||
인자 | num | 요소의 개수 | |
size | 각 요소의 바이트 단위 크기 | ||
반환값 |
힙 역역에 할당된 메모리 덩어리 중 첫 번째 바이트 메모리의 주소 할당된 메모리 크기는 num 인자와 size 인자의 값을 곱한 크기 |
||
설명 | 이 함수는 malloc() 함수와 달리 할당받은 메모리를 0으로 초기화하여 전달한다. |
////
#include<stdio.h>
//malloc(), calloc() 함수를 위한 헤더 포함
#include<stdlib.h>
//memset() 함수를 위한 헤더 포함
#include<string.h>
int main(void) {
// 선언할 배열 요소의 크기를 기술하지 않았지만 초깃값을 기준으로 자동으로 크기가 결정된다. (NULL 문자 포함)
char szBuffer[] = { "Hello" };
//"Hello" 문자열이 저장된 메모리의 주소로 초기화되는 포인터 변수
char* pszBuffer = "Hello"; // 동적할당 x
//동적 할당한 메모리의 주소가 저장될 포인터 선언 및 정의
char* pszData = NULL;
//메모리를 동적으로 할당하고 "Hello"문자열로 초기화
pszData = (char*)malloc(sizeof(char) * 6);
pszData[0] = 'H';
pszData[1] = 'e';
pszData[2] = 'l';
pszData[3] = 'l';
pszData[4] = 'o';
pszData[5] = '\0';
puts(szBuffer);
puts(pszBuffer);
puts(pszData);
free(pszData);
return 0;
}
이러한 방식으로도 다룰수 있다.
메모리 복사
배열처럼 여러 인스턴스가 뭉쳐진 경우엔 절대로 단순 대입으로 r-value를 l-value로 복사할 수 없습니다.
memcpy() 함수를 이용하여 인수로 전달된 두 주소의 메모리에 담긴 정보를 복사할 수 있습니다.
void *memcpy(void *dest, const void *serc, size_t count) | |||
인자 | dest | 대상 메모리 주소 | |
src | 복사할 원본 데이터가 저장된 메모리 주소 | ||
count | 복사할 메모리의 바이트 단위 크기 | ||
반환값 | 대상 메모리 주소 | ||
설명 | 특정 주소로 시작하는 일정 길이의 메모리에 저장된 값을 대상 메모리에 그대로 복사해준다. |
#include<stdio.h>
//malloc(), calloc() 함수를 위한 헤더 포함
#include<stdlib.h>
//memset() 함수를 위한 헤더 포함
#include<string.h>
int main(void) {
char szBuffer[12] = { "HelloWorld" };
char szNewBuffer[12] = { 0 };
memcpy(szNewBuffer, szBuffer, 4);
puts(szNewBuffer);
memcpy(szNewBuffer, szBuffer, 6);
puts(szNewBuffer);
memcpy(szNewBuffer, szBuffer, 12);
puts(szNewBuffer);
return 0;
}
'szNewBuffer = szBuffer;' 라는 코드의 개념적 의미는 짐작할수 있지만, 문법적으로는 절대 허용되지 않는 연산입니다.
그러므로, 이연산이 가능하도록 하려면 각 배열의 요소만큼 반복문을 수행하여 요솔별로 일일이 단순 대입 연산을 수행해주어야 합니다. 그러나 이 귀찮은 일을 memcpy() 함수가 대신 할 수 있습니다.
메모리 비교 - memcmp(), strcmp()
int memcmp(const void *buf1, const void *buf2, size_t count); | |||
인자 | buf1 | 비교 원본 메모리 주소 | |
buf2 | 비교 대상 메모리 주소 | ||
count | 비교할 메모리의 바이트 단위 크기 | ||
반환값 |
결과가 0이면 두 값은 같음 0보다 크면 buf1이 buf2보다 더 큼 0보다 작으면 buf2가 buf1보다 더 큼 단, 뺄셈 연산을 수행할 때 unsigend char형으로 처리, 따라서 -1은 255로 처리 |
||
설명 | 첫 번째 인자로 전달된 주소의 메모리에 저장된 값에서 두 번째 인자로 전달된 주소에 저장된 메모리의 값을 뺴서 두 값이 같은지 비교한다. 즉, 주어진 길이만큼 두 메모리를 비교하는 함수이다. |
int strcmp(const char *string1, const char *string2); | |||
인자 | string1 | 비교할 문자열이 저장된 메모리 주소 | |
string2 | 비교할 문자열이 저장된 메모리 주소 | ||
반환값 |
두 문자열이 같으면 0 반환 만일 0보다 큰 수를 반환하면 string1이 string2보다 알파벳 순서상 나중이고, 0보다 작으면 string2가 나중임을 의미 |
||
설명 | 대소문자를 식별하여 두 문자열이 같은지를 비교하는 함수 |
#include<stdio.h>
#include<string.h>
int main(void) {
char szBuffer[12] = { "TestString" };
char* pszData = "TestString";
// 다음 코들은 주소와 상관없이 대상 메모리에 ㅔ저장된 문자열이 같은 비교한다.
// 만일 길이가 다르면 무조건 같은 문자열이 아니다.
printf("%d\n", strcmp(szBuffer, pszData));
printf("%d\n", strcmp("TestString", pszData));
printf("%d\n", strcmp("Test", pszData));
return 0;
}
문자열 검색 - strstr()
char *strstr(const char *string, const char *strCharSet); | |||
인자 | string | 검색 대상이 될 문자열이 저장된 메모리 주소 | |
strCharSet | 검색할 문자열이 저장된 메모리 주소 | ||
반환값 |
문자열을 찾으면 해당 문자열이 저장된 메모리 주소 반환 찾지 못하면 NULL 반환 |
||
설명 | 임의의 대상 문자열에서 특정 문자열을 검색하는 함수 |
*(기준주소 + 인덱스) 나 기준주소[인덱스] 나 같은 의미입니다.
realloc(), sprintf() 함수
void *realloc(void *memblock, size_t siez); | |||
인자 | memblock |
기존에 동적 할당된 메모리 주소 만일 이 주소가 NULL이면 malloc() 함수와 동일하게 동작 |
|
size | 다시 할당받을 메모리의 바이트 단위 크기 | ||
반환값 |
다시 할당된 메모리 덩어리 중 첫 번째 바이트의 메모리 주소 만일 다시 할당하는 데 실패하면 NULL 반환 이 경우 첫 번째 인자로 전달된 메모리를 수동으로 해제해야 함 |
||
설명 |
만일 이미 할당된 메모리 영역에서 크기를 조정할 수 있다면, 반환된 주소는 첫 번째 인자로 전달된 주소와 같다. 그러나 불가능하다면 기존의 메모리를 해제하고 새로운 영역에 다시 할당한 후, 새로 할당된 메모리의 주소를 반환한다. |
int sprintf(char *buffer, const char *format [, argument] ...); | |||
인자 | buffer | 출력 문자열이 저장될 메모리 주소 | |
format | 형식 문자열이 저장된 메모리 주소 | ||
[, argument] | 형식 문자열에 대응하는 가변 인자들 | ||
반환값 | 출력된 문자열의 개수 | ||
설명 | 형식 문자열에 맞추어 특정 메모리에 문자열을 저장하는 함수 |
ex) sprintf(pszNewBuffer, "%s", "TestStringData");
'언어 > C' 카테고리의 다른 글
Call by value, Call by reference - 독하게 시작하는 C프로그래밍 (0) | 2019.10.03 |
---|---|
포인터의 배열과 다중 포인터 - 독하게 시작하는 C프로그래밍 (0) | 2019.09.21 |
포인터와 배열 - 독하게 시작하는 C프로그래밍 (0) | 2019.09.18 |
메모리의 종류 / 직접 지정, 간접 지정 - 독하게 시작하는 C프로그래밍 (0) | 2019.09.18 |
[Inflearn C] 달팽이 배열 Snail_Array (0) | 2019.09.09 |
- Total
- Today
- Yesterday
- C
- 자료구조
- 구조체
- codeit
- 직접 지정
- 공용체
- inflearn
- Algorithm
- 간접 지정
- timecomplexity
- 2차원 배열
- 포인터
- 종류
- 공부
- 공간복잡도
- call by reference
- 시간복잡도
- 프로그래밍
- 재귀함수
- 형승격
- 알고리즘
- 파이썬
- 비트필드
- 강의
- 3차원 배열
- 다차원 배열
- call by value
- 배열
- 회전리스트
- 1차원 배열
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |