반응형

 memset 함수는 시작 주소값부터 sz 바이트만큼, 바이트 단위로 초기화를 해 주는 함수입니다. 보통 2번째 인자에 넣는 값이 0, -1인 경우가 상당히 많은데요. 0x3f나 0x7f 등도 ps에는 꽤 많이 쓰입니다. 그런데, 바이트 단위로 초기화를 하기 때문에, int형 배열이나 long long형 배열과 같은 경우, 배열에 memset 함수로 0, -1은 넣을 수 있는데, 2, 3과 같은 건 넣을 수 없습니다. 이런 건 조심해야 합니다. 사용 방법은 아래와 같습니다.

 

 

void *memset(void *tar, int value, size_t sz);

 

 

 요약하면, tar부터, sz byte만큼 바이트 단위로 value라는 값으로 초기화를 하겠다는 의미입니다.

 

 


 먼저 예제 프로그램 1을 봅시다. 보시면 10만개짜리 int형 배열인 arr이 있어요. 저는, arr의 모든 영역을 0이라는 값으로 초기화 하고 싶어요. 그러면 1번째 인자는 arr, 3번째 인자는 sizeof(int)*100000이 될 겁니다.

 

 

 그러면 바이트 단위로 메모리를 보면, 0x00, 0x00, ... 이런 식으로 초기화가 될 거에요. 이걸 4byte씩 읽어봅시다.

 

 

 무려 0이 나오는군요. 즉 0은 16진수로, 0xabababab 패턴에 걸리기 때문에, 해당 함수로 초기화가 가능합니다.

 

 

 그러면, 이건 어떨까요? 2번째 인자가 0x3f인 경우에는? 당연하게도 바이트 단위로 보면, 0x3f 0x3f, ... 이런 식으로 메모리에 들어갈 거에요. 이걸 그림으로 나타내면 아래와 같습니다.

 

 

 역시, 0x3f3f3f3f는 0xABABABAB 패턴에 속합니다. 따라서, int형 배열에서, memset으로 초기화를 할 수 있는 수 중 하나가 되겠습니다. 보통, 이 값은 무한대를 선언할 때 많이 쓰입니다. 0x3f3f3f3f에 2를 곱해도, int형을 벗어나지 않거든요. 당연하게도, long long형에서는 inf를 0x3f3f3f3f3f3f3f3fLL로 많이 선언하는 편이고요. 그러면 int형 배열을 왜 1로 멤셋으로 초기화 하는 건 불가능할까요?

 

 

 0xABABABAB 패턴이 아니기 때문입니다. 1은 0x00000001입니다. 그러면 이 경우는 어떨까요?

 

 

 char형이 1바이트라면, 저렇게 초기화 해도 크게 문제 없습니다. '.'은 아스키 코드로 0x2e이기 때문에, k가 0보다 크거나 같고, 20보다 작다면 str[k] = 0x2e로 초기화가 됩니다. 초기화 되는 단위랑 char형의 크기가 같기 때문에, 이렇게 써도 문제 없습니다.

 

 


 그런데, 이 함수가 byte 단위로 초기화를 하다 보니, 잘못 사용하면 런타임이 뜨는 경우가 있습니다. 간혹 가다 백준에 올라와 있는 질문을 답변해 주다 보면, string이나 vector, map이 들어있는 자료형에다가 memset을 썼다던지 하는 경우가 있는데요. 이런 경우는 문제가 될 소지가 있어요. 심지어 이들은 pod type이 아닙니다.

 

 그런데 pod type이라도, 해당 함수를 잘못 사용하는 경우 런타임이 걸리는데요. 예제를 봅시다.

 

 

 12번째 줄에 arr[0].p가 "chogahui"라는 리터럴을 가리키게 해 놓았습니다. 다음에 13번째 줄에서, arr 배열을 byte 단위로 0x3f라는 값으로 초기화를 합니다. 그러면 어떻게 되는지 그림을 그려보겠습니다.

 

 

 원래, arr[0].p는 "abcdef"와 같은 리터럴을 가지고 있는 주솟값을 들고 있었어요. 그런데, 이게 뜬금없이 0x3f...3f 로 바뀌었습니다. 그러면 어떻게 될까요?

 

 

 arr[0].p가 이상한 공간을 가리킬 겁니다. 여기에 접근하면 어떻게 될까요? 읽고 쓴다면? 펑 하고 터질 겁니다. 바이트 단위로 초기화 하기 때문에, 이렇게 주솟값을 같이 들고 있는 경우, memset으로 섣불리 초기화 하면 안 됩니다.

 

 

 그러면, 이 경우는 어떨까요? 배열이 있네요. 배열 같은 경우에는 그냥 자료 형이에요. int형 4개짜리를 연속적으로 저장할 수 있는 어떠한 공간의 이름이 arr 필드인 것입니다. 그러면 필드 값을 init 하는 것과 같은데요.

 

 

 고로 memset으로 초기화를 해도 큰 문제가 없습니다.

반응형

댓글을 달아 주세요

  1. 곰곰지영

    공감 꾹~
    주말 마무리 잘 하세요 :)

  2. 베스트터치

    공부를 넘 많이 하셨네요. ㄷㄷ

  3. 허니듀크

    전 웹퍼블쪽 일을 하고 있습니다. C도 관심이 있었는데 역시 어렵긴하네요. 웹쪽도 많이 올려주세요.~ ^^

  4. junl

    "0은 16진수로, 0xabababab 패턴에 걸리기 때문에, 해당 함수로 초기화가 가능합니다"
    에서 0xabababab 패턴이 뭔가요? 또 0xABABABAB 패턴은 뭔가요? 무슨 의미인지 잘 이해가 되지 않습니다.

    • 코딩강아지
      2021.10.29 16:37 신고

      헥사로 표현했을 때
      0은 0x00000000이니까 memset로 가능하다는 의미입니다.

      0xABABABAB 패턴은 예를 들자면
      0x3f3f3f3f 이러한 것들을 의미합니다.