메뉴 닫기

C 스타일 문자열(char 배열) 완전 정복: strlen, strcpy, strcmp 사용법까지


C 스타일 문자열(char 배열) 완전 정복: strlen, strcpy, strcmp 사용법까지

🧵 C++ 문자열 다루기의 기초부터 실전 함수 활용까지 한 번에 배워보세요

C++을 배우다 보면 문자열 처리에 대해 혼란스러울 때가 많습니다.
특히 C 스타일 문자열은 객체가 아니라 char 배열로 다루기 때문에 기본적인 개념부터 정확히 이해하는 것이 중요하죠.
저도 처음엔 ‘\0’이 왜 필요한지조차 헷갈렸던 기억이 납니다.
이 글에서는 C 스타일 문자열의 구조를 명확하게 짚고, 실무나 문제풀이에서 자주 사용하는 strlen, strcpy, strcmp 등의 함수까지 단계적으로 익혀보도록 할게요.
처음 배우는 분들도 어렵지 않게 이해할 수 있도록 천천히, 꼼꼼하게 설명해드릴게요.

C 스타일 문자열은 객체 지향적인 std::string과 달리, char 배열에 null 문자(‘\0’)로 끝나는 구조를 가지고 있습니다.
이 특성을 잘 이해해야 각종 문자열 함수들을 정확하게 사용할 수 있고, 메모리 오류나 예외 상황도 줄일 수 있어요.
이번 글에서는 C++에서 흔히 사용되는 문자열 처리 방식 중 하나인 C 스타일 문자열을 집중적으로 살펴보고, 다음과 같은 내용을 다룰 예정입니다.







🔤 C 스타일 문자열이란?

C 스타일 문자열은 문자들의 배열(char array)로 구성되며, null 문자(‘\0’)를 통해 문자열의 끝을 나타냅니다.
이 방식은 C 언어의 전통적인 문자열 처리 방식으로, 메모리를 효율적으로 사용할 수 있다는 장점이 있지만, 문자열의 길이, 안전성, 복사 등에 신경을 써야 하는 단점도 존재합니다.

예를 들어 다음과 같이 선언할 수 있습니다.

CODE BLOCK
char greeting[6] = {'H', 'e', 'l', 'l', 'o', '\0'};

이 배열은 문자 ‘H’부터 ‘o’까지 총 5개의 문자와 마지막에 문자열 종료를 나타내는 ‘\0’을 포함하여 6개의 요소로 구성됩니다.
이처럼 C 스타일 문자열에서는 반드시 문자열 끝에 ‘\0’을 포함해야 하며, 그렇지 않으면 프로그램이 의도치 않게 메모리를 참조하여 오류나 보안 취약점이 발생할 수 있습니다.

⚠️ 주의: ‘\0’ 문자가 누락된 문자열은 끝을 알 수 없기 때문에, 문자열 관련 함수 사용 시 무한 루프나 예외 오류로 이어질 수 있습니다.

또한 문자열 리터럴로 선언하는 경우, 컴파일러가 자동으로 null 문자를 추가해줍니다.

CODE BLOCK
char greeting[] = "Hello"; // 자동으로 마지막에 '\0' 추가됨

이처럼 C 스타일 문자열은 간단하면서도 정확한 규칙이 존재하며, 해당 규칙을 기반으로 다양한 문자열 함수들이 동작하게 됩니다.


📏 문자열 길이 구하기 – strlen

문자열의 길이를 알아내기 위해 가장 많이 사용하는 함수는 strlen()입니다.
이 함수는 C 스타일 문자열에서 null 문자(‘\0’)를 기준으로 문자열의 길이를 계산합니다.
즉, 문자열 내부에 포함된 문자 수만 반환하며, ‘\0’ 자체는 길이에 포함되지 않습니다.

CODE BLOCK
#include <cstring>
#include <iostream>

int main() {
    char text[] = "OpenAI";
    std::cout << strlen(text); // 출력: 6
    return 0;
}

위 예시에서 “OpenAI”는 총 6개의 문자로 구성되어 있으며, strlen 함수는 \0 이전까지의 문자 수를 세기 때문에 결과는 6이 됩니다.

💡 TIP: strlen()은 단순한 계산 함수이지만, 반복문을 통해 문자열 끝을 탐색하기 때문에 길이가 긴 문자열을 반복 호출하면 성능 저하가 발생할 수 있어요.

또한 strlen은 단순히 \0을 만날 때까지 순회하기 때문에 초기화되지 않은 배열이나 누락된 종료 문자를 가진 문자열에 대해 예기치 않은 결과를 반환할 수 있습니다.

⚠️ 주의: strlen()을 사용할 때는 문자열이 반드시 ‘\0’으로 끝나는지 확인하세요.
그렇지 않으면 메모리 범위를 벗어나 세그먼트 오류(segmentation fault)가 발생할 수 있습니다.

이처럼 strlen은 간단하지만 반드시 안전한 조건에서 사용해야 하는 함수입니다.
문자열이 유효한지, null 종료 문자가 있는지를 항상 확인하는 습관을 들이면 좋습니다.







📦 문자열 복사 – strcpy

C 스타일 문자열을 다룰 때 자주 사용되는 함수 중 하나가 strcpy()입니다.
이 함수는 두 문자열 간의 복사를 수행하며, 소스 문자열의 내용을 대상 문자열에 그대로 복사해 줍니다.
다만, 버퍼 크기를 고려하지 않으면 버퍼 오버플로우 같은 심각한 문제가 발생할 수 있습니다.

CODE BLOCK
#include <cstring>
#include <iostream>

int main() {
    char source[] = "C Programming";
    char destination[50];

    strcpy(destination, source);
    std::cout << destination; // 출력: C Programming
    return 0;
}

위 코드에서 destination 배열의 크기(50)가 충분히 크기 때문에 안전하게 복사가 이루어졌습니다.
그러나 destination 배열의 크기가 source보다 작을 경우, 예기치 못한 메모리 침범이 발생할 수 있습니다.

⚠️ 주의: strcpy는 복사 대상 버퍼의 크기를 확인하지 않기 때문에, 반드시 복사 대상의 크기를 직접 관리해 주어야 합니다.

보다 안전한 방식으로는 strncpy()를 사용할 수 있습니다.
이 함수는 복사할 최대 길이를 지정할 수 있어 버퍼 오버플로우 위험을 줄일 수 있습니다.

CODE BLOCK
strncpy(destination, source, sizeof(destination) - 1);
destination[sizeof(destination) - 1] = '\0'; // null 종료 보장

strncpy를 사용할 때도 null 종료 문자가 자동으로 붙지 않을 수 있기 때문에 수동으로 마지막에 ‘\0’을 추가하는 것이 안전한 습관입니다.


⚖️ 문자열 비교 – strcmp

두 문자열이 같은지 비교할 때 사용하는 대표적인 함수가 strcmp()입니다.
이 함수는 두 문자열의 내용을 한 글자씩 비교하여,
완전히 동일하면 0을 반환하고,
앞쪽 문자열이 더 크면 양수, 작으면 음수를 반환합니다.

CODE BLOCK
#include <cstring>
#include <iostream>

int main() {
    char a[] = "apple";
    char b[] = "banana";

    int result = strcmp(a, b);
    std::cout << result; // 출력: 음수
    return 0;
}

위 예시에서는 문자열 a가 b보다 사전 순으로 앞서기 때문에 strcmp()는 음수를 반환합니다.
이처럼 strcmp는 문자열을 단순히 같은지 아닌지만 판단하는 것이 아니라, 사전 순 정렬이나 정렬 알고리즘 구현에도 자주 사용됩니다.

💡 TIP: 두 문자열이 같은지 단순히 확인하고 싶다면 strcmp(str1, str2) == 0으로 비교하면 됩니다.

또한 대소문자를 구분하지 않고 비교하고 싶을 땐 strcasecmp() 혹은 _stricmp()와 같은 함수(시스템에 따라 다름)를 사용할 수 있어요.

CODE BLOCK
#ifdef _WIN32
#include <string.h> // _stricmp
#define strcasecmp _stricmp
#else
#include <strings.h> // strcasecmp
#endif

이처럼 strcmp는 단순한 비교 이상의 용도로 활용될 수 있으며, 다양한 문자열 처리를 위한 기반 도구로 매우 중요합니다.







🧼 안전하게 문자열 다루기

C 스타일 문자열을 다룰 때 가장 중요한 점은 바로 안전성입니다.
문자열의 길이를 정확히 파악하지 않거나, null 종료 문자가 누락된 상태에서 함수들을 사용하는 경우 치명적인 오류로 이어질 수 있습니다.
이를 방지하기 위해서는 몇 가지 체크리스트를 항상 기억해야 해요.

  • 🔐모든 문자열은 반드시 ‘\0’으로 끝나야 합니다.
  • 📏버퍼 크기는 항상 여유 있게 선언하세요.
  • 🧪strcpy, strcat보다는 strncpy, strncat을 사용하는 것이 안전합니다.
  • 🧯입력받은 문자열은 항상 검증하고 필터링해야 합니다.
  • 🧼불필요한 문자열 연산을 줄이고, std::string 사용을 고려해 보세요.

C 스타일 문자열은 메모리 효율과 단순한 구조로 인해 시스템 프로그래밍 등에서 여전히 널리 사용되지만, 그만큼 안전성에 취약할 수 있습니다.
따라서 사용하는 함수와 선언 방식에 대해 항상 조심스럽게 접근해야 하며, 안전한 습관을 들이는 것이 가장 중요합니다.

💎 핵심 포인트:
단순히 작동한다고 끝나는 것이 아닙니다.
C 스타일 문자열은 정확하게 선언하고, 안전하게 처리하고, 예외에 대비하는 습관이 필수입니다.

만약 문자열 관련 작업이 많고 복잡한 프로젝트라면, std::string 사용을 고려하는 것도 좋은 선택이 될 수 있습니다.
표준 문자열 클래스는 메모리 관리와 예외 처리가 자동으로 되어 있어 보다 안정적인 코드 작성이 가능합니다.


자주 묻는 질문 (FAQ)

strlen 함수는 null 문자를 포함하나요?
아니요. strlen 함수는 문자열 끝의 ‘\0’ 문자를 포함하지 않고, 그 이전까지의 문자 수만 계산합니다.
strcpy를 사용할 때 어떤 문제가 발생할 수 있나요?
대상 버퍼의 크기를 초과하여 복사하면 버퍼 오버플로우가 발생할 수 있으며, 이는 메모리 오류나 보안 문제로 이어질 수 있습니다.
strcmp는 어떤 값을 반환하나요?
두 문자열이 같으면 0, 앞 문자열이 더 크면 양수, 작으면 음수를 반환합니다.
strncpy는 왜 더 안전하다고 하나요?
복사할 최대 길이를 지정할 수 있어, 버퍼 크기를 넘지 않도록 제어할 수 있기 때문입니다.
‘\0’ 문자는 꼭 필요할까요?
반드시 필요합니다. C 스타일 문자열은 ‘\0’을 통해 문자열 끝을 판단하기 때문에 없으면 오류가 발생할 수 있습니다.
문자열 복사를 반복하면 성능에 영향을 줄 수 있나요?
네. 특히 strlen 같은 함수는 매번 문자열 끝까지 탐색하므로 반복 사용 시 성능 저하가 발생할 수 있습니다.
대소문자를 구분하지 않고 비교할 수 있나요?
가능합니다. strcasecmp 또는 _stricmp 같은 함수를 사용하면 대소문자 구분 없이 비교할 수 있습니다.
std::string과 char 배열 중 어떤 것이 더 좋은가요?
std::string은 메모리 관리와 예외 처리에 있어 더 안전하고 편리하지만, char 배열은 성능과 제어 측면에서 유리할 수 있습니다. 용도에 따라 선택하세요.



🧠 C 스타일 문자열을 제대로 이해하면 메모리 오류를 피할 수 있습니다

이번 글에서는 C++에서 자주 사용하는 C 스타일 문자열(char 배열)에 대해 알아봤습니다.
문자열의 끝을 표시하는 null 문자(‘\0’)를 이해하는 것부터 시작해, strlen으로 길이를 확인하고, strcpy로 안전하게 복사하며, strcmp로 비교하는 과정까지 실전 예제와 함께 익혀봤죠.
특히 메모리 관련 오류나 버퍼 오버플로우를 방지하기 위한 안전한 습관도 함께 짚어봤습니다.

처음에는 다소 복잡하게 느껴질 수 있지만, 문자열 처리의 기본기를 탄탄하게 다져두면 이후에 std::string이나 더 고급 문법으로 넘어갈 때 큰 도움이 됩니다.
기초지만 매우 중요한 C 스타일 문자열, 이번 기회에 꼭 확실히 익혀보시기 바랍니다.


🏷️ 관련 태그:C++, 문자열처리, char배열, strcpy, strcmp, strlen, C스타일문자열, 버퍼오버플로우, null문자, 안전한코딩