35.3 메모리 내용을 한꺼번에 설정하기

포인터를 역참조한 뒤 값을 할당할 때는 해당 자료형 크기만큼만 할당할 수 있습니다. 만약 int형 포인터라면 4바이트 크기만큼 할당하겠죠?

memset 함수를 사용하면 메모리의 내용을 원하는 크기만큼 특정값으로 설정할 수 있으며 함수 이름은 memory set에서 따왔습니다(string.h 헤더 파일에 선언되어 있습니다). 이때 설정하는 크기는 바이트 단위입니다.

  • memset(포인터, 설정할값, 크기);
    • void *memset(void *_Dst, int _Val, size_t _Size);
    • 값 설정이 끝난 포인터를 반환

다음 내용을 소스 코드 편집 창에 입력한 뒤 실행해보세요.

memory_set.c

#include <stdio.h>
#include <stdlib.h>    // malloc, free 함수가 선언된 헤더 파일
#include <string.h>    // memset 함수가 선언된 헤더 파일

int main()
{
    long long *numPtr = malloc(sizeof(long long));  // long long의 크기 8바이트만큼 동적 메모리 할당

    memset(numPtr, 0x27, 8);    // numPtr이 가리키는 메모리를 8바이트만큼 0x27로 설정

    printf("0x%llx\n", *numPtr);    // 0x2727272727272727: 27이 8개 들어가 있음

    free(numPtr);    // 동적으로 할당한 메모리 해제

    return 0;
}

실행 결과

0x2727272727272727

먼저 memset 함수를 사용하려면 string.h 또는 memory.h 헤더 파일을 포함해야 합니다. 그리고 memset 함수에 포인터, 설정할 값, 설정할 크기를 넣으면 됩니다. 여기서는 memset(numPtr, 0x27, 8);과 같이 사용했으므로 numPtr이 가리키는 메모리에는 16진수 27이 8개 들어가게 됩니다.

memset 함수는 주로 다음과 같이 설정할 값을 0으로 지정하여 메모리의 내용을 모두 0으로 만들 때 주로 사용합니다.

memset(numPtr, 0, 8);    // numPtr이 가리키는 메모리를 8바이트만큼 0으로 설정
참고 | 자료형의 크기와 포인터의 크기

memset 함수에 설정할 크기를 지정할 때 보통 숫자 대신 sizeof를 사용합니다.

long long *numPtr = malloc(sizeof(long long));

memset(numPtr, 0, sizeof(long long));   // numPtr이 가리키는 메모리를 long long 크기만큼 0으로 설정

여기서 메모리를 sizeof(long long)크기만큼 할당했으므로 설정할 크기도 sizeof(long long)과 같이 지정해야 하며 sizeof(long long *)과 같이 포인터의 크기를 지정하면 안 됩니다. 포인터의 크기는 메모리 주소의 크기일 뿐 실제 메모리가 차지하는 크기가 아닙니다. 이 부분은 char 포인터에 메모리를 할당해보면 잘 알 수 있습니다.

char *cPtr = malloc(sizeof(char));    // char의 크기 1바이트만큼 동적 메모리 할당

memset(cPtr, 0, sizeof(char));    // char의 크기 1바이트만큼 0으로 설정(올바른 방법)
memset(cPtr, 0, sizeof(char *));  // 32비트: char 포인터의 크기 4바이트만큼 0으로 설정(잘못된 방법)
                                  // 64비트: char 포인터의 크기 8바이트만큼 0으로 설정(잘못된 방법)
free(cPtr);

memset(numPtr, 0, sizeof(char));는 메모리를 1바이트만큼 0으로 설정하니 문제가 없습니다. 하지만 memset(numPtr, 0, sizeof(char *));는 32비트에서 4바이트, 64비트에서 8바이트만큼 0으로 설정하므로 할당받은 메모리 크기를 넘어서게 됩니다.

다른 예로 32비트에서 sizeof(long long)은 8바이트인데 sizeof(long long *)는 4바이트이므로 할당받은 메모리보다 작은 공간을 설정하게 됩니다(64비트에서 sizeof(long long *)는 8이라 그냥 크기가 일치한 것일 뿐 잘못된 방법입니다).

long long *numPtr = malloc(sizeof(long long));   // long long의 크기 8바이트만큼 동적 메모리 할당

memset(numPtr, 0, sizeof(long long));     // long long의 크기 8바이트만큼 0으로 설정(올바른 방법)
memset(numPtr, 0, sizeof(long long *));
                          // 32비트: long long 포인터의 크기 4바이트만큼 0으로 설정(잘못된 방법)
                          // 64비트: long long 포인터의 크기 8바이트만큼 0으로 설정(잘못된 방법)
free(numPtr);

memset 함수에서 sizeof를 사용할 때는 이러한 부분을 주의해야 합니다.