42 문자열을 복사하고 붙이기

이번에는 문자열을 다른 곳으로 복사하는 방법과 두 문자열을 붙이는 방법을 알아보겠습니다.

42.1 문자열 복사하기

문자열은 다른 배열이나 포인터(메모리)로 복사할 수 있습니다. strcpy 함수는 문자열을 다른 곳으로 복사하며 함수 이름은 string copy에서 따왔습니다(string.h 헤더 파일에 선언되어 있습니다).

  • strcpy(대상문자열, 원본문자열);
    • char *strcpy(char *_Dest, char const *_Source);
    • 대상문자열의 포인터를 반환

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

string_copy_array_to_array.c

#define _CRT_SECURE_NO_WARNINGS    // strcpy 보안 경고로 인한 컴파일 에러 방지
#include <stdio.h>
#include <string.h>    // strcpy 함수가 선언된 헤더 파일

int main()
{
    char s1[10] = "Hello";    // 크기가 10인 char형 배열을 선언하고 문자열 할당
    char s2[10];              // 크기가 10인 char형 배열을 선언

    strcpy(s2, s1);        // s1의 문자열을 s2로 복사
    
    printf("%s\n", s2);    // Hello

    return 0;
}

실행 결과

Hello

먼저 "Hello" 문자열이 들어있는 배열 s1과 아무것도 들어있지 않은 배열 s2를 선언했습니다. 그리고 strcpy(s2, s1)와 같이 strcpy 함수에 복사된 결과가 저장될 문자열과 복사할 문자열을 넣습니다. 이렇게 하면 s2s1의 문자열이 복사됩니다.

그림 42‑1 strcpy 함수로 문자열 복사

복사된 결과가 저장될 배열의 크기는 반드시 NULL까지 들어갈 수 있어야 합니다. 크기가 더 작다면 복사가 되더라도 문자열이 정상적으로 출력되지 않습니다. 따라서 "Hello" 문자열이 복사되려면 배열의 크기는 최소한 6이 되어야 합니다.

지금까지 문자 배열(char형 배열)을 사용하여 문자열을 복사했습니다. 그러면 문자열 포인터에 복사하면 어떻게 될까요? 다음 내용을 소스 코드 편집 창에 입력한 뒤 F5 키를 눌러서 디버깅 모드로 실행해보세요.

string_copy_pointer_to_pointer_error.c

#define _CRT_SECURE_NO_WARNINGS    // strcpy 보안 경고로 인한 컴파일 에러 방지
#include <stdio.h>
#include <string.h>    // strcpy 함수가 선언된 헤더 파일

int main()
{
    char *s1 = "Hello";    // 문자열 포인터
    char *s2 = "";         // 문자열 포인터

    strcpy(s2, s1);    // 실행 에러

    printf("%s\n", s2);

    return 0;
}

실행 결과

0xC0000005: 0x013A585D 위치를 기록하는 동안 액세스 위반이 발생했습니다.

strcpy 함수로 문자열 포인터 s1을 문자열 포인터 s2로 복사했습니다. 복사가 될 것 같지만 실행을 해보면 에러가 발생합니다. 왜냐하면 s2에 저장된 메모리 주소는 복사할 공간도 없을뿐더러 읽기만 할 수 있고, 쓰기가 막혀있기 때문입니다.

그림 42‑2 읽기 전용 메모리에는 문자열을 복사할 수 없음
참고 | 문자열과 읽기 전용 메모리

char *s1 = "Hello"; char *s2 = "";과 같은 문자열 포인터에 할당된 문자열 리터럴은 왜 읽기 전용일까요?

C 언어 컴파일러는 문자열 포인터에 할당한 문자열 리터럴을 실행 파일의 읽기 전용 데이터 섹션(데이터 세그먼트)에 배치하기 때문입니다. 따라서 실행 파일이 실행된 뒤에는 읽기 전용 메모리가 되며 쓰기를 할 수 없습니다. 다음은 각 운영체제별 읽기 전용 데이터 섹션 이름입니다.

  • Windows PE: .rdata
  • 리눅스 ELF: .rodata
  • OS X Mach-O: __TEXT, __cstring

문자열 포인터에 문자열을 복사하려면 문자열이 들어갈 공간을 따로 마련해야 됩니다. 따라서 다음과 같이 malloc 함수로 메모리를 할당한 뒤 문자열을 복사합니다.

string_copy_pointer_to_memory.c

#define _CRT_SECURE_NO_WARNINGS    // strcpy 보안 경고로 인한 컴파일 에러 방지
#include <stdio.h>
#include <string.h>    // strcpy 함수가 정의된 헤더 파일
#include <stdlib.h>    // malloc, free 함수가 선언된 헤더 파일

int main()
{
    char *s1 = "hello";                      // 문자열 포인터
    char *s2 = malloc(sizeof(char) * 10);    // char 10개 크기만큼 동적 메모리 할당

    strcpy(s2, s1);        // s1의 문자열을 s2로 복사

    printf("%s\n", s2);    // Hello

    free(s2);    // 동적 메모리 해제

    return 0;
}

실행 결과

Hello

char *s2 = malloc(sizeof(char) * 10);처럼 char 10개 크기만큼 동적으로 메모리를 할당했습니다. 이렇게 하면 strcpy 함수로 s1의 문자열을 s2에 복사해서 넣을 수 있습니다.

문자열 사용이 끝났다면 반드시 free 함수로 동적 할당한 메모리를 해제합니다.

그림 42‑3 strcpy 함수로 문자열 포인터에 문자열 복사