문자열은 프로그램을 작성할 때 거의 항상 사용한다.
C언어는 문자열 표현을 위해 null로 종결되는 단순한 ASC2 문자열을 사용할 수 밖에 없다.
그런데 단순한 문자 배열로 문자열을 표현하면, 버퍼 오버플로 같은 보안 위험 등 여러가지 문제가 발생한다.
C++ STL은 더 안전하고 사용하기 쉬운 std::string 클래스를 제공하여, C스타일 문자열의 단점을 피할 수 있다.
2.1 동적 문자열
프로그래밍 언어에서 문자열은 최 우선순위로 지원되는 기능이다.
자유자재로 바꾸는 크기는 물론, 부분추출, 추출하여 바꾸기 등의 여럭 고급 기능을 지원한다.
하지만, C에서의 문자열 지원은 상당히 부실한데, 단순히 문자의 배열만 존재하고, 편리하게 사용할 수 있는 문자열 데이터 타입이 따로 존재하지 않는다.
문자열 라이브러리 조차 아주 기초적인 기능만 지원하고, 무려 배열 경계에 대한검사도 제대로 하지않는다.
2.1.1 C 스타일 문자열
C언어에서 문자열은 문자의 배열로 표현된다.
문자열의 마지막 문자는 언제나 null('\0')로 채워지고, 코드에서는 null문자를 체크하여 문자열의 끝 임을 판단한다.
null문자는 공식적으로는 NUL로 알려져 있는데, L을 두번 쓰지 않고 한 번만 쓴다.
NUL은 NULL포인터와는 다르다!.
C++가 C보다 더 나은 문자열 추상화 타입을 제공하지만, C 스타일 문자열에 사용된 테크닉을 C++에서도 사용할 일이 생각보다 많이 발생하기 때문에 이해는 하고 있어야 한다.
프로그래머들이 C 스타일 문자열을 사용할 때 가장 흔하게 하는 실수는 문자열 마지막에 '\0' 을 넣는걸 까벅는 것이다.
예를들어 문자열 "hello" 를 표현하는데 사용하는 글자는 5개 이지만, 공간은 6개 할당해주어야 한다.
C++에서는 C의 여러 문자열 처리 함수를 내장한다.
이 함수들은 <cstring> 헤더 파일에 정의되어 있다.
C스타일로 문자열 복사하기
기본적으로 이 함수들은 메모리 관리를 하지 않는데, 예를들어 strcpy()함수는 두 개의 문자열 포인터를 받아서 첫번째 문자열에 두번쨰 문자열을 복사해주는데, 첫 번째 문자열이 적합한 메모리 공간을 가졌는지는 전혀 신경쓰지 않는다.
만약 이러한 사실을 보완하려고 다음과 같은 함수를 작성하여, 보완할 수 있다.
char* copyString(const char* char)
{
char* result = new char[strlen(str) + 1];
strcpy(result, str);
return result;
}
strlen()은 메모리 크기가 아닌 문자 개수만 리턴하기 때문에 +1을 붙여서 공간 한개를 더 추가해주어야 한다.
C스타일로 문자열 이어붙이기
이러한 사실을 응용해서 strcpy와 strcat을 사용하여 문자열을 이어붙일 수 있다.
char* appendStrings(cosnt char* str1, const char* str2, const char* str3)
{
char* result = new char[strlen(str) + strlen(str2) + strlen(str3) + 1];
srtcpy(result, str1);
strcat(result, str2);
strcat(result, str3);
return result;
}
C와 C++에서는 sizeof()를 사용해서 데이터 타입이나 변수의 크기를 알 수 있다.
예를들어 sizeof(char)는 1을 리턴한다. char타입은 크기가1 바이트 이기 때문이다.
그런데, C스타일 문자열에서는 sizeof()값이 strlen() 과 다르다는것에 주의해야 한다.
문자열 크기를 측정할 때 주의점
문자열의 크기를 얻을 때 에는 절대 sizeof()를 이용해서는 안된다.
만약 C스타일 문자열이 char[]타입으로 저장되어 있다면, sizeof()가 null문자열을 포함한 문자열의 크기를 알려준다.
char text1[] = "abcdef";
size_t s1 = sizeof(text1); //7
size_t s2 = strlen(text1); //6
하지만, C 스타일 문자열이 char*형태로 저장되어 있다면, sizeof()는 포인터 타입의 크기를 리턴해버린다.
const char* text2 = "abcdef";
size_t s3 = sizeof(text2); // 32비트면 4 64면 8
size_t s4 = strlen(text2); // 6
32비트 모드로 컴파일 하면 s3의 값이 4가 되지만, 64면 8로 나타난다.
const char*는 포인터 이기 때문에, 주소표현범위 크기를 리턴하기 때문이다.
C스타일 문자열 함수는 대부분 보안위험을 초래하기 때문에( 주소값을 직접참조해버림 ) 그래서, 경고메세지를 출력하고 함수가 사용할 수 없다고 나타난다. 이러한 경고 메세지는 strcpy_s()나 strcat_s()를 사용하면 방지할 수 있다.
'전문가를 위한 C++정리' 카테고리의 다른 글
2. 문자열의 활용 2.1 동적 문자열 2.1.3 C++ string 클래스 (0) | 2024.01.12 |
---|---|
2. 문자열의 활용 2.1 동적 문자열 2.1.2 문자열 리터럴 (0) | 2024.01.12 |
1. C++와 STL 부딪혀보기 1.5 첫 C++ 프로젝트 1.5.1 ~ 1.6 요약 (0) | 2024.01.11 |
1. C++와 STL 부딪혀보기 1.4 표준 라이브러리 1.4.1 std::vector (0) | 2024.01.11 |
1. C++와 STL 부딪혀보기 1.3 객체지향 언어로서의 C++ 1.3.1 클래스의 정의 (0) | 2024.01.11 |