(VS C/C++)배열의 문자열을 지정한 크기만큼 복사하는 strncpy_s, strncpy함수

visual studio c/c++, gcc,c++ C/C++언어

이 글에서는 문자열을 지정한 크기만큼 복사하는 Visual Sudio C/C++의 함수에 대해서 소개합니다.

전제 조건

이 글은 다음의 내용을 전제 조건으로 작성했습니다.

문자열 상수 정의하기

우선, 다음 코드에서 정의한 배열 변수 cpySource의 크기가 얼마인지 확인해 봅시다.

#include <stdio.h>
void main() {
    const char cpySource[] = "ABCDEFGHIJ";
    printf("size of cpySource = %d\n", (int)sizeof(cpySource));
}

실행 결과, 다음과 같이 A부터 J까지의 문자 갯수는 10개지만 cpySource 배열의 크기는 11이 출력 되었습니다.

C:\Test002\x64\Debug>Test002.exe
size of cpySource = 11

ABCDEFGHIJ“의 문자 갯수와 배열 변수에 설정된 크기가 다른 이유는 다음과 같습니다.

char cpySource[] = “ABCDEFGHIJ”; 실행 결과로 cpySource 변수는 다음과 같이 설정됩니다.

배열
index
012345678910
ABCDEFGHIJ0x00
이 표는 “복사 원본 문자열” 의 메모리 상태입니다.

핵심 포인트

배열로 선언한 변수에 문자열은 설정하면 배열에 마지막은 널문자 0x00가 설정됩니다. 문자열의 크기는 시작 문자에서 널문자 0x00 발견되는 곳까지를 의미합니다. 무슨 이유에서든지 있어야 할 곳에 0x00가 존재하지 않는다면 참조 범위 이외의 메모리를 참조하려고 하기 때문에 메모리 참조 에러가 발생하는 원인이 됩니다.

더 큰 배열 영역에 복사하기

다음 코드는 A부터 J까지 10개의 문자로 구성된 문자열 즉 “복사 원본 문자열”을 더 큰 100 크기의 배열 즉 “복사 사본 배열” 변수에 복사합니다.

#include <stdio.h>
#include <string.h>
void main() {
    const char cpySource[] = "ABCDEFGHIJ";
    char copyDest1[100];
    memset(copyDest1, 0x00, sizeof(copyDest1));
    printf("size of cpySource = %d\n", (int)sizeof(cpySource));
    printf("size of copyDest1 = %d\n", (int)sizeof(copyDest1));
    strncpy_s(copyDest1, sizeof(copyDest1), cpySource, sizeof(copyDest1)-1);
    printf("cpySource=%s\n",cpySource);
    printf("copyDest1=%s\n",copyDest1);
}

실행 결과, strncpy_s 함수에 지정할 “복사 최대 크기“는 sizeof(copyDest1)-1 의 99입니다만 이보다 작은 11 크기의 “복사 원본 문자열” cpySource가 복사되었음을 확인할 수 있습니다.

C:\Test002\x64\Debug>Test002.exe
size of cpySource = 11
size of copyDest1 = 100
cpySource=ABCDEFGHIJ
copyDest1=ABCDEFGHIJ

copyDest1 변수에는 다음과 같이 복사됩니다.

배열
index
01234567891099100
ABCDEFGHIJ0x000x000x000x00
이 표는 Test002.exe 실행 결과 “복사 사본 배열” 의 메모리 상태입니다.

더 작은 배열 영역에 복사하기

다음 코드는 A부터 J까지10개의 문자로 구성된 문자열 즉 “복사 원본 문자열”을 더 작은 5 크기의 배열 즉 “복사 사본 배열” 변수에 복사합니다.

#include <stdio.h>
#include <string.h>
void main() {
    const char cpySource[] = "ABCDEFGHIJ";
    char copyDest1[5];
    memset(copyDest1, 0x00, sizeof(copyDest1));
    printf("size of cpySource = %d\n", (int)sizeof(cpySource));
    printf("size of copyDest1 = %d\n", (int)sizeof(copyDest1));
    strncpy_s(copyDest1, sizeof(copyDest1), cpySource, sizeof(copyDest1)-1);
    printf("cpySource=%s\n",cpySource);
    printf("copyDest1=%s\n",copyDest1);
}

실행 결과, strncpy_s 함수에 지정한 “복사 최대 크기sizeof(copyDest1)-1 의 4로 인해서 copyDest1에는 A부터 D까지 4개의 문자가 복사되고 마지막에 0x00 값이 설정되었음을 알 수 있습니다.

C:\Test002\x64\Debug>Test002.exe
size of cpySource = 11
size of copyDest1 = 5
cpySource=ABCDEFGHIJ
copyDest1=ABCD

copyDest1 변수에는 다음과 같이 복사됩니다.

배열
index
01234
ABCD0x0
이 표는 Test002.exe 실행 결과 “복사 사본 배열” 의 메모리 상태입니다.

“복사 최대 크기” 지정 오류

참고로 위에서 설명한 “더 작은 배열 영역에 복사하기“의 경우, 다음과 같이 strncpy_s 함수에 지정할 “복사 최대 크기“에 다음과 같이 sizeof(copyDest1) 는 5를 지정하면 메모리 에러가 발생합니다.

strncpy_s(copyDest1, sizeof(copyDest1), cpySource, sizeof(copyDest1));

C:\Test002\x64\Debug>Test002.exe

그 이유는 다음과 같이 “복사 최대 크기” 5만큼 전부 문자로 채워져 컴퓨터 메모리 copyDest1에 문자열의 끝을 알리는 널문자 0x0가 설정되지 못했기 때문 입니다.

배열
index
01234
ABCDE

이 오류를 해결하기 위해서는 다음과 같이 조건을 만족해야 합니다.

  • 복사 원본 문자열복사 사본의 배열 변수의 크기가 같고 복사 원본의 문자열0x00로 끝날 것
    const char cpySource[] = "ABCDEFGHIJ";
    char copyDest1[11];
  • 복사 원본 문자열 크기 보다 복사 사본의 배열 변수의 크기가 더 클 것
  • 본사 원본 문자열 크기 보다 복사 사본의 배열 변수의 크기가 더 작은 경우 strncpy_s함수에 지정 할 “복사 최대 크기“에 복사 사본의 배열 변수의 크기 -1 을 설정할 것

핵심 포인트

복사 최대 크기“는 배열의 마지막 위치에 널문자 0x00를 설정하도록 (배열전체 크기 -1)를 설정해야 합니다.

“복사 최대 크기” 지정 방법 비교

strncpy_s 함수에 지정할 “복사 최대 크기“는 다음과 같이 2가지의 지정 방법이 있습니다. 어느 쪽이든 같은 결과를 얻을 수 있습니다.

strncpy_s(copyDest1, sizeof(copyDest1), cpySource, sizeof(copyDest1)-1);
strncpy_s(copyDest1, sizeof(copyDest1), cpySource, _TRUNCATE);
제목과 URL을 복사했습니다