프로그래밍 공부
작성일
2024. 1. 12. 17:09
작성자
WDmil
728x90

문자열은 프로그램을 작성할 때 거의 항상 사용한다.

 

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()를 사용하면 방지할 수 있다.

 

 

728x90