[Basic C++] #2 C 스타일의 문자열, char*, const char*
C++ STL에서 제공하는 std::string 클래스 이전에,
C에서 제공하는 문자열의 주요 특징들에 대하여 알아보겠습니다.
C 스타일 문자열의 장점과 단점
1. 장점
- 단순하다. 기본 문자 타입과 배열 구조만 사용한다.
- 가볍다.
- 저수준이다.
- 익숙하다.
2. 단점
- 범용 문자열 데이터 타입으로, 고급 작업 시 많은 시간이 소요된다.
- 메모리 작업에 민감하고, 디버깅 과정에서 버그를 찾기 어렵다.
- C++의 객체지향 개념을 사용 할 수 없다.
- 문자열 내부 동작 방식을 모두 이해해야 한다.
헤더 파일
#include <cstring>
코드 예제, strlen, strcpy
char* copyString(const char* str)
{
char* result = new char[strlen(str)+1];
strcpy(result, str);
return result;
}
C언어에서 문자열은 문자의 배열로 표현됩니다. 이떼, 문자열의 마지막은 항상 null 문자로 채워집니다.
"strlen" 함수는 문자열 길이를 반환하는 함수로, 마지막 null 문자를 제외한 문자열 크기를 반환합니다.
"strcpy" 함수는 문자열 복사 함수로, 인수로 넘겨받은 두 문자열이 적합한 메모리 공간을 확보했는지 확인하지 않습니다. 따라서, 복사를 실행할 문자열의 크기를 먼저 확보하고, strcpy 함수를 호출합니다.
코드 예제, strlen, strcat
char* apeendStrings (const char* str1, const char* str2, const char* str3)
{
char* result = new char[strlen(str1) + strlen(str2) + strlen(str3) + 1];
strcpy(result, str1);
strcpy(result, str2);
strcpy(result, str3);
return result;
}
"strcat" 함수는 인수로 넘겨받은 두 문자열을 이어 붙입니다.
코드 예제, sizeof() vs strlen()
char str1[] = "abcedf";
size_t s1 = sizeof(str1); // 7 반환
size_t s2 = strlen(str1); // 6 반환
const char* str1 = "abcedf";
size_t s1 = sizeof(str1); // 결과 예층 불가
size_t s2 = strlen(str1); // 6을 반환
"sizeof"를 통해 배열에 들어있는 자료들의 총 데이터 타입 크기를 알 수 있습니다.
하지만, char* 타입으로 정의된 문자열의 경우, sizeof는 포인터 타입의 크기를 리턴하므로 주의해야 합니다.
문자열 리터럴, 리터럴 풀링
cout << "hello world" << endl; // ""로 표현한 문자열 리터럴
문자열 리터럴의 경우, 읽기 전용 메모리에 할당됩니다. 따라서 메모리 사용을 절약합니다.
코드 안에서 "hello world"를 여러 번 사용하여도, 하나의 "hello world" 메모리를 할당받고, 나머지는 해당 영역을 참조하게 됩니다. 이러한 방식을 리터럴 풀링이라고 합니다.
const char* str1 = "hello world";
str1[0] = 'a'; // 정의되지 않은 동작, 에러 발생 가능
const char str1[] = "hello world";
str1[0] = 'a'; // "hellow world" -> "aello world"로 변경됩니다.
문자열 리터럴은 변수에 대입될 수 있습니다. 하지만, 읽기 전용 메모리에 위치하여 리터럴 풀링이 적용되어 있을 가능성이 높습니다. 따라서, 해당 메모리에 쓰기 혹은 수정 동작을 시도할 경우 에러가 발생할 수 있습니다. 웬만하면 const char* 타입으로 선언하여, 쓰기 작업을 미연에 방지하는 것이 좋습니다.
반면에, 문자열 배열의 초깃값으로 선언할 경우, 해당 배열은 읽기 전용 메모리에 두거나, 리터럴 풀링이 적용되지 않아, 쓰기 작업이 가능해집니다.
'언어 > Basic C++' 카테고리의 다른 글
[Basic C++] #6_오버라이딩과 오버로딩의 차이점 (0) | 2022.03.07 |
---|---|
[Basic C++] #5 메서드 종류, static 메서드, const 메서드 (0) | 2022.03.07 |
[Basic C++] #4 데이터 멤버의 종류, static, const (0) | 2022.03.07 |
[Basic C++] #3_얕은 복제, 깊은 복제 (0) | 2022.03.06 |
[Basic C++] #1 Map, Unordered_map, 해쉬 테이블 (0) | 2022.02.23 |