C언어/string.h

[C언어] strncpy 함수 (문자열 복사)

아무일도없었다 2022. 10. 3. 22:07

사용범위

Windows, Unix 등 모든 OS에서 사용 가능한 표준 API 함수

기능

C언어 표준 함수로 string 을 복사하는 데 사용한다.

헤더

#include <string.h>

※ 함수 사용시 string.h 파일을 include 하지 않는다면 컴파일 시 error 발생 ※


함수

char* strncpy(char* dest, const char* source, size_t count);

파라미터

  • char* dest
    • destination 의 약자로 복사한 문자열을 저장할 대상의 버퍼를 입력한다.
    • 반드시 유효한 주소값을 입력해야 하고 유효하지 않은 주소 입력 시 signal 이 발생한다.
  • const char* source
    • dest 에 복사할 데이터 버퍼를 입력한다.
  • size_t count
    • source 에서 dest 에 복사할 문자의 개수를 입력한다.

반환 값

복사된 string 의 주소 값 (pointer) 를 반환한다. ( ret = char* dest )

잡학지식

strncpy 함수 size 를 직접 입력할 수 있어서 strcpy 함수에 비해 안전하지만 여전히 위험성이 있기 때문에 사용 시 주의를 해야 하며, 아래의 strncpy 함수의 특징들을 알고 있어야 한다.

 

우선 source 의 문자열 길이 (NULL 로 종료 지점 확인) 보다 count 가 짧다면 나머지 count 만큼 NULL('\0') 문자로 채운다. 다시 말해 count 가 source 의 크기보다 작다면 나머지 count 에 해당되는 버퍼는 NULL('\0') 로 채워진다.

 

두 번째로 dest 의 버퍼 크기보다 큰 count 를 입력하면 dest 버퍼를 넘어서 복사를 하기 때문에 버퍼 오버플로우 버그가 발생한다. 따라서 반드시 count 의 크기는 dest 의 크기보다 작아야 한다.

 

세 번째로 dest 에 문자열이 복사된 이후 마지막에 NULL('\0') 문자를 붙이지 않기 때문에 사용 시 주의가 필요하다.

strcpy 함수는 복사 이후 마지막에 NULL('\0) 문자를 추가하지만 strncpy 함수는 NULL('\0') 문자를 붙이지 않는다.

따라서 strncpy 사용시 count 를 sizeof(dest) 로 입력하고 마지막 문자에 NULL 을 수동으로 입력하기도 한다.

 

마지막으로 source 는 NULL 문자로 종료되는 문자열 사용을 권장한다. (혹은 dest 와 source 중에 크기가 작은 버퍼를 기준으로 count 값 입력) strncpy 함수는 NULL 을 기준으로 문자열의 종료를 확인하는데 source 에 NULL 문자가 없다면 source 를 넘어서 복사할 수 있기 때문에 버퍼 오버플로우 버그가 발생할 여지가 생길 수 있기 때문이다.

 


 

<소스 코드 1>

#include <stdio.h>

int main() {
    char buffer1[8] = {0,};
    char buffer2[8] = {0,};
    int i;

    strcpy(buffer1, "ABCDE");
    strcpy(buffer2, "FGH");
    printf("buffer1[%s] buffer2[%s]\n", buffer1, buffer2);

    // return value = buffer1
    strncpy(buffer1, buffer2, 3);

    printf("string copy (buffer1 <- buffer2) buffer1[%s]\n", buffer1);

    for(i=0; i<8; i++) {
        printf("buffer1[%d]:[%c]\n", i, buffer1[i]);
    }

    return 0;
}

 

※ 실행 결과

buffer1[ABCDE] buffer2[FGH]
string copy (buffer1 <- buffer2) buffer1[FGHDE]
buffer1[0]:[F]
buffer1[1]:[G]
buffer1[2]:[H]
buffer1[3]:[D]
buffer1[4]:[E]
buffer1[5]:[ ]
buffer1[6]:[ ]
buffer1[7]:[ ]

 

<소스 코드 1> 에서는 buffer2 의 문자열("FGH") 길이 3 만큼만 복사를 했기 때문에 buffer1 에 ("FGHDE") 가 저장된 것을 확인할 수 있다.

 


 

<소스 코드 2>

#include <stdio.h>

int main() {
    char buffer1[8] = {0,};
    char buffer2[8] = {0,};
    int i;

    strcpy(buffer1, "ABCDE");
    strcpy(buffer2, "FGH");
    printf("buffer1[%s] buffer2[%s]\n", buffer1, buffer2);

    // return value = buffer1
    strncpy(buffer1, buffer2, sizeof(buffer1));
    // last NULL
    buffer1[sizeof(buffer1) - 1] = '\0';

    printf("string copy (buffer1 <- buffer2) buffer1[%s]\n", buffer1);

    for(i=0; i<8; i++) {
        printf("buffer1[%d]:[%c]\n", i, buffer1[i]);
    }

    return 0;
}

 

※ 실행 결과

buffer1[ABCDE] buffer2[FGH]
string copy (buffer1 <- buffer2) buffer1[FGH]
buffer1[0]:[F]
buffer1[1]:[G]
buffer1[2]:[H]
buffer1[3]:[ ]
buffer1[4]:[ ]
buffer1[5]:[ ]
buffer1[6]:[ ]
buffer1[7]:[ ]

 

<소스 코드 2> 에서는 buffer1 길이 8 만큼 복사를 했기 때문에 buffer2 의 FGH 문자열 복사 이후 뒤쪽에 NULL 문자로 채워진 문자열을 확인할 수 있다. (+ 수동으로 마지막 문자에 NULL 을 입력하였다.)

반응형