개발관련 이것저것

memset 주의사항

Drill_Labito 2023. 1. 14. 18:20

Reference : https://stackoverflow.com/questions/37780779/memset-to-int-max-in-c

 

이전에 다익스트라 글을 쓰면서, 

 

int dist[MAX_V];

bool sptSet[MAX_V]; 

 

이 두 배열을 초기화 하는 방식에서 loop 문을 돌면서 초기화 해주고 있었다. 

사실 초기화작업만 따지면 memset 이 더 빠르기 때문에 memset 을 사용한 초기화를 해주고 싶었다. 

 

먼저 해당 코드를 살펴보자. 

#include <iostream>
#include <limits.h>

using namespace std;

#define MAX_V 9

int main()
{
    int dist[MAX_V];
    bool sptSet[MAX_V];

    for(int i = 0; i < MAX_V; ++i)
    {
        dist[i] = INT_MAX;
        sptSet[i] = false;
    }
}

INT_MAX 는 limits.h 헤더파일에 정의된 값으로 int 의 양수 최대값인, 2147483647 이 들어있다. 

먼저 loop 문을 이용하여 초기화 하였을 때, 결과물을 보면 다음과 같았다.

 

이런식으로 배열을 loop문으로 초기화하는 방식을 memset 초기화 방식으로 바꿔주고자했다. 

 

#include <iostream>
#include <limits.h>

using namespace std;

#define MAX_V 9

int main()
{
    int dist[MAX_V];
    bool sptSet[MAX_V];

#if 0
    for(int i = 0; i < MAX_V; ++i)
    {
        dist[i] = INT_MAX;
        sptSet[i] = false;
    }
#else
    memset(dist, INT_MAX, sizeof(dist));
    memset(sptSet, false, sizeof(sptSet));
#endif
}

memset 으로 했을 때 결과물은 다음과 같았다.

 

 

두 방식에서 차이가 발생하는데, 왜 이런지 이유를 몰랐다. 

memset 함수 정의를 보면 아래와 같다.

( Reference : https://www.ibm.com/docs/ko/i/7.3?topic=functions-memset-set-bytes-value )

전처리문은 둘째치더라도, 2번째 인자로 int 값을 가져오고 있었다. 

하지만, stackoverflow 에 똑같이 문의된 글에서 답변을 살펴보니, 

 

Reading the documentation (always a good idea when code does not work as expected): void *memset(void *s, int c, size_t n); "The memset function copies the value of c (converted to an unsigned char) into each of the first n characters of the object pointed to by s."

 

( memset 관련 문서1 : https://cplusplus.com/reference/cstring/memset/ )

( memset 관련 문서2 : https://en.cppreference.com/w/cpp/string/byte/memset )

( memset 관련 문서3 : https://www.tutorialspoint.com/c_standard_library/c_function_memset.htm )

 

memset 관련한 문서를 살펴보면, 2번째 인자로 들어온 int 값을 복사하여 unsigned char 로 형변환해서 사용하고 있다.

즉, 인자로 들어온 int 는 4바이트지만, 내부적으로는 unsigned char 범위의 숫자까지만 허용한다는 점이다. 

( 1바이트 = 8비트 : 2^8 = 256 까지 표현가능 ) 

따라서 INT_MAX 는 4바이트 값에서 나올 수 있는 최대값을 사용하기 때문에, memset 에 해당값을 넣으면 오버플로우가 나서 이상하게 값이 초기화되었던 것이다. 

 

따라서 1바이트 범위를 넘는 수로 초기화하는경우는 그냥 loop문을 통해 초기화할 수 있도록 해야겠다.