티스토리 뷰

C 또는 C++ 언어에서, 구조체 또는 배열을 초기화할 때 memset 함수를 사용하는 것을 종종 볼 수 있습니다.

#ifdef CPP    // C++에서는 cstring 헤더를 사용합니다(string.h 를 사용해도 됩니다)
#include <cstring>
#elif
#include <string.h>
#endif

int main()
{
    int array[100];
    memset(array, 0, sizeof(array));
    ...
]

 

이 때 사용하는 memset 함수의 시그니처는 다음과 같습니다 :

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

 

 

 

주의사항


일반적으로 0으로 초기화하고자할 때 memset은 유용한 선택이 될 수 있지만, 그 외의 경우 얘기가 다릅니다.

memset 함수는 cpluscplus.com에서 다음과 같이 정의합니다 :

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

메모리 블록을 채웁니다.
ptr 포인터에 의해 지정된 메모리 블록의 num 바이트만큼을 지정된 value로 채웁니다(unsigned char로 해석됨)

 

위 레퍼런스로부터 눈여겨 봐야할 것은 메모리 블록을 채운다는 부분입니다. 이 때 메모리 블록을 채우는 기준은 1byte(8bit) 이기 때문에, 0이 아닌 다른 값으로 메모리를 초기화하고자할 때 문제가 발생할 수 있습니다.

 

예를 들어, 위 배열을 1로 채우기 위해서 memset(array, 1, sizeof(array)) 를 사용하게 되면 unsigned char는 1바이트, int는 4바이트이기 때문에 다음과 같이 채워질 것입니다.

arr pointer
 |
 0x00000001 | 0x0000001 | 0x000001 | ...     // 사용자가 기대한 메모리 초기화
 -----------------------------------
 0x01010101 | 0x01010101 | 0x01010101 | ...    // memset이 수행한 메모리 결과

 

결과적으로, array 배열은 다른 값으로 채워지게 됩니다. 만약 array 배열이 char 또는 unsigned char형이었다면, 올바른 값이 들어가게 됩니다.

 

아래의 코드 또는 디버거를 사용하여 메모리 내부의 값들을 확인할 수 있습니다 :

/* Windows OS에서 작성됨 */
#include <iostream>
#include <cstring>
using namespace std;

int main()
{
    int array[100];
    memset(array, 1, sizeof(array));

    size_t size = sizeof(int) * 8;
    for (int i = 0; i < size; ++i)
        cout << ((array[0] >> (size - (i + 1))) & 1);
    cout << "\n";

    return 0;
}

 

또한, memset의 2번째 인자는 내부적으로 unsigned char로 해석된다고 언급되어 있습니다. 앞서 언급한 사항을 숙지하지 못한 채 2번째 인자를 255보다 큰 값을 집어넣게 되어도 제대로된 초기화가 수행될 수 없습니다(앞선 사항을 숙지하고 있다면 두 번째 값을 0 ~ 255 이외의 값을 넣을 일도 없을 것입니다).

 

만약 257(0x0101)으로 값을 초기화하려고 한다면 255 이상의 값은 무시되고 1(0x0001)로 초기화하게 됩니다.

 

 

 

배열 초기화에 대한 다른 대안


아쉽게도 2바이트 / 4바이트 / 8바이트에 대한 메모리 초기화에 대응되는 공식적인 memset 함수는 없습니다. 다만, C++의 경우, algorithm 헤더의 std::fill 함수를 통해 초기화를 수행할 수 있습니다.

/* Windows OS에서 작성됨 */
#include <iostream>
#include <algorithm>
using namespace std;

int main()
{
    int array[100];
    fill(array, array + 100, 257);

    ...
}

 

 

 

레퍼런스


참고자료
cplusplus.com - memset

'개발 > Miscellaneous' 카테고리의 다른 글

퍼포스 로컬 서버 구축하기(Perforce local Server)  (0) 2020.04.26
리눅스마스터 2급 실기 정리  (11) 2020.04.24
YSE Sound Library  (0) 2019.11.29
DestroyWindow와 PostQuitMessage의 차이  (0) 2019.11.26
시그윈(Cygwin)  (0) 2019.06.15
댓글