<개인공부>/[C언어, C++]

[C언어/C++] memset 함수 메모리 초기화

BlockDMask 2020. 11. 5. 00:30
반응형

안녕하세요. BlockDMask 입니다.
오랜만에 C언어, C++주제를 포스팅 하네요.
2020년 남은 11월 12월에는 C언어 C++주제는 목요일에 포스팅할 예정입니다.
일요일에는 파이썬 남은 문법들을 진행할 예정입니다.

오늘 C언어 C++의 메모리를 초기화 해줄 수 있는 memset 함수에 대해서 시작해보겠습니다.

<목차>
1. memset 함수란?
2. memset 함수 예제


1. C언어, C++에서의 memset 함수


memset 함수는 메모리의 내용(값)을 원하는 크기만큼 특정 값으로 세팅할 수 있는 함수 입니다.
함수이름이 정말 명확하죠? memory + setting 메모리를 (특정 값으로) 세팅한다.
기억하기 쉬울것 입니다. 그럼이제 함수를 하나하나 쪼개서 분해해 볼까요?

함수 원형
void* memset(void* ptr, int value, size_t num);

첫번째 인자 void* ptr은 세팅하고자 하는 메모리의 시작 주소.
즉, 그 주소를 가리키고 있는 포인터가 위치하는 자리 입니다.

두번째 인자 value는 메모리에 세팅하고자 하는 값을 집어 넣으면 됩니다.
int 타입으로 받지만 내부에서는 unsigned char 로 변환되어서 저장됩니다. 즉 'a' 이런것을 넣어도 무방하다는 뜻입니다.

세번째 인자 size_t num은 길이를 뜻합니다. 이 길이는 바이트 단위로써 메모리의 크기 한조각 단위의 길이를 말합니다. 이는 보통 "길이 * sizeof(데이터타입)" 의 형태로 작성하면 됩니다.

반환값은 성공하면 첫번째 인자로 들어간 ptr을 반환하고, 실패한다면 NULL을 반환합니다.

 
아 그리고, 헤더파일은 memory.h 혹은 string.h 둘중 하나를 사용해도 무방합니다. 두개다 memset 함수가 정의되어있기 때문입니다. (둘다 써도 괜찮아요)

아래 예제로 들어가기 전에 간단하게 예제를 한번 작성해보겠습니다.
char arr[] = "blockdmask";
memset(arr, 'c', 5 * sizeof(char));
print(arr);

이런식으로
첫번째 인자에는 변경하고자 하는 목적지의 첫번째 주소(포인터)를 넣고,
두번째 인자에는 변경하고자 하는 값 'c'를 넣었습니다.
그리고 마지막 인자에는 변경하고자 하는 길이 5를 넣고 char 배열이 들어왔으므로 char 타입의 바이트 크기를 계산해서 곱해주었습니다. 그렇게 해서 바이트 길이를 넣어준 것 입니다.

그럼 이제 진짜 예제로 가서 이해를 좀더 해볼까요.


2. C언어, C++ memset 함수 예제


예제1) 문자 배열 변경

1
2
3
4
5
6
7
8
9
10
11
12
#include<string.h> // #include<memory.h> 도 괜찮습니다.
#include<stdio.h>
 
int main(void)
{
    char arr1[] = "blockdmask blog";
    memset(arr1, 'c'5 * sizeof(char));
    printf(arr1);
 
    return 0;
}
 
cs


결과에서 보셨듯 배열 "blockdmask blog"에서 앞자리 5자리가 'c' 값으로 초기화 된 것을 볼 수 있습니다.


예제2) 배열 초기화 for문과 memset

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
32
33
34
35
36
#include<memory.h> //#include<string.h>
#include<stdio.h>
 
void printAll(int* pArr, int len)
{
    for (int i = 0; i < len; ++i)
    {
        printf("%d "*(pArr + i));
    }
 
    printf("\n\n");
}
 
int main(void)
{
    // 배열 초기화 for 문 이용
    int arr1[20];
    for (int i = 0; i < 20++i)
    {
        arr1[i] = 0;
    }
 
    printf("for    : ");
    printAll(arr1, 20);
 
 
    // 배열 초기화 memset 함수이용
    int arr2[20];
    memset(arr2, 020 * sizeof(int));
 
    printf("memset : ");
    printAll(arr2, 20);
 
    return 0;
}
 
cs


이렇게 배열을 0으로 초기화를 해야할때 for 반복문을 이용하기도 하지만, 이렇게 memset 함수를 이용해서 초기화 할 수 도 있습니다.


예제3) 주의 사항

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include<memory.h>
#include<string.h> // 둘다 포함해도 노상관
#include<stdio.h>
 
int main(void)
{
    int arr[5];
    
    // 0 이 아닌 다른 값으로 세팅
    memset(arr, 1sizeof(arr));
 
    for (int i = 0; i < 5++i)
    {
        printf("%d "*(arr + i));
    }
    
    return 0;
}
 
cs

결과에서 보셨듯이 0이 아닌 int 타입의 숫자를 넣게되면 예상할 수 없는 값으로 세팅 됩니다. 그 이유는 memset 함수는 1 바이트 단위로 값을 초기화 하기 때문입니다. 1바이트 단위로 1를 만들었기 때문에 4바이트로 표현된 int 숫자 1은 제대로된 숫자로 표현될 수 없습니다. 

0은 4바이트든 1바이트든 0 이기 때문에 동일한 결과값을 기대할 수 있던 것 입니다.

결론적으로
0 이아닌 그리고 char 타입이 아닌 값을 넣어서 세팅 하려고 할때는 우리가 원하는 값으로 세팅할수 없습니다.
즉, 0이랑 char 타입만 사용하시길!
그렇기 때문에 memset 함수는 보통 문자열(char 배열)에서 값을 변경하거나, 숫자배열을 0으로 세팅할때 사용하곤 합니다.


이렇게 오늘은 memset 함수에 대해서 알아보았습니다.
아직은, 파이썬 보다 C, C++이 편하긴 하네요.
파이썬이 접근하기 쉽다고는 하지만 역시 익숙한거 만큼은 아닌가 봅니다.

반응형