C

memset

GunwooYun 2022. 8. 23. 00:25

흔히 memset 을 사용하는 용도로는 함수명 그대로 memory에 저장된 값을 특정한 값으로 치환하기 위해서다.

 

예를 들면 다음과 같다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include<stdio.h>
#include<string.h>
 
int main()
{
    char str[30= "hello, world";
 
    printf("%s\n", str);
 
    memset(str, 0sizeof(str));
 
    printf("%s\n", str);
    
 
    return 0;
}  
cs

위의 코드는 "hello, world" 라는 문자열로 초기화 되어 있는 char 배열 str을 널값 0 로 초기화하는 것이다.

 

당연히 출력하면 아무것도 안 나온다.

 

함수 원형은 다음과 같다.

 

void* memset(void* ptr, int value, size_t num);

 

먼저 초기화 할 데이터의 주솟값을 첫 인자로, 수정할 값을 두번째, 마지막으로 길이(바이트 단위) 이다.

 

보통은 0으로 초기화를 한다. 예를 들면 int 형 배열을 0으로 초기화 할 때, 반복문을 사용해도 되지만 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
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
 
int main()
{
    char str[30= "hello, world";
    
    int arr[20];
 
    printf("%s\n", str);
 
    memset(str, 0sizeof(str));
 
    printf("%s\n", str);
 
    for(int i = 0; i < sizeof(arr) / sizeof(int); i++)
        arr[i] = 1;
 
    for(int i = 0; i < sizeof(arr) / sizeof(int); i++)
        printf("%d ", arr[i]);
    
   memset(arr, 0, 20 * sizeof(int));
 
    for(int i = 0; i < sizeof(arr) / sizeof(int); i++)
        printf("%d ", arr[i]);
 
    return 0;
}  
cs

 

위의 코드에서 1로 초기화 한 arr[20] 은 memset을 통해 0으로 치환된다. 문제는 memset 을 통해 값을 치환할 경우 0 이나 -1은 제 값이 잘 들어가는데, 이 외의 다른 값들은 이상하게 들어간다. 출력하면 이렇게 나온다.

 

memset(arr, 1, sizeof(int) * 8)

arr[20] 의 값을 byte 단위로 총 32byte 만큼 1로 초기화 했다. 상식 선에서는 1, 1, 1, ... 1 이렇게 출력될 것 같지만, 실제는 저 숫자, 84215045 이렇게 출력된다. 왜 그럴까?

 

디버깅에서 저장된 메모리를 확인하면 다음과 같다.

memset(arr, 1, sizeof(int)*20)

각 바이트는 1로 초기화 되었고, int는 4 바이트이므로 0x01010101 로 초기화되었다.

 

출력 화면은 다음과 같다. 16843009, 계산기로 확인결과 값은 마찬가지다.

출력 화면

아, memset은 바이트 단위로 초기화하기 때문에 int 형으로 출력하게 되면 4바이트를 읽어들여 10진수로 변환한다.

그래서 0x01010101 을 10진수로 변환해 16843009 란 값이 나오는구나...

 

그럼 왜?? -1은 잘 될까? 그 이유는 -1은 0xFFFFFFFF 의 10진수 정수이므로 문제없이 출력이 된 것이다.

 

memset의 활용은 아무래도 문자열의 문자를 변경할때가 아닌가 싶다. 1바이트 단위로 값을 변경하거나, 0으로 초기화 할때 반복문을 활용하는 것보단 memset으로 쉽게 초기화하는게 맞지 않나 싶다.