이이프
IeF 제멋대로 세상
이이프
전체 방문자
오늘
어제

공지사항

  • ✔ Info
  • 전체 글보기 (56)
    • 💻프로그래밍 내용 정리 (55)
      • C (0)
      • C++17 (55)
    • 💻게임메이커 (0)
    • 💻언리얼엔진 (0)
    • 💻유니티 (0)
    • 🎈[팀&자작]게임소개 (0)
    • 📃게임제작기술 (0)
    • 🎨그림놀이 (0)
    • 📒대학생활 (0)
    • 😃잡담 (1)
    • 🕹게임성과 (0)
    • 💷자격증 (0)

블로그 메뉴

  • 방명록

최근 글

최근 댓글

티스토리

hELLO · Designed By 정상우.
이이프

IeF 제멋대로 세상

💻프로그래밍 내용 정리/C++17

[C++ 2.1.1] 동적 스트링(C 스타일 스트링), strlen, strcpy, strcat

2022. 8. 19. 16:36
728x90

C 스타일 스트링

C 언어는 스트링 문자 배열로 표현했다.

스트링의 마지막에 널 문자(\0)를 붙여서 스트링이 끝났음을 표현했다.

이러한 널 문자에 대한 공식 기호는 NUL이다.

L이 두 개가 아니라 하나며 NULL 포인터와는 다른 값이다.

아직도 C 스타일 스트링을 쓰는 C++ 프로그램이 많기 때문에 C 언어 스타일 스트링을 알아둘 필요가 있다.

 

C  스트링을 다룰 때 \0 문자를 담을 공간을 깜박하고 할당하지 않는 실수를 저지르기 쉽다.

예를 들어 'hello'란 스트링을 구성하는 문자는 다섯 개이지만,

메모리에 저장할 때는 문자 여섯 개만큼의 공간이 필요하다.

myString 'h' 'e' 'l' 'l' 'o' '\0'

 

C++은 C 언어에서 사용하던 스트링 연산에 대한 함수도 제공한다.

이러한 함수는 <cstring> 헤더 파일에 정의돼 있다.

 

예를 들어 strcpy() 함수는 스트링 타입 매개변수를 두 개 받아서 두 번째 스트링을 첫 번째 스트링에 복사한다.

다음 코드는 주어진 스트링에 딱 맞게 메모리를 할당한 결과를 리턴하는 함수를

strcpy()에 대한 래퍼 함수 형태로 구현한 예를 보여주고 있다.

여기서 스트링의 길이는 strlen() 함수로 구한다.

char* copyString(const char* str)
{
	char* result = new char[strlen(str)]; // 버그! 한 칸 부족하다.
	strcpy(result, str);
	return result;
}

위 copyString() 함수 코드에 오류가 하나 있다.

strlen() 함수에서 리턴하는 값은 스트링을 저장하는 데 사용된 메모리 크기가 아니라 스트링 길이를 리턴한다.

따라서 strlen()은 'hello'란 스트링에 대해 6이 아닌 5를 리턴한다.

따라서 스트링을 저장하는 데 필요한 메모리를 제대로 할당하려면 문자 수에 1을 더한 크기로 지정해야 한다.

char* copyString(const char* str)
{
	char* result = new char[strlen(str) + 1]; // 버그! 한 칸 부족하다.
	strcpy(result, str);
	return result;
}

 

스트링 세 개를 하나로 합쳐서 리턴하는 함수를 생각해보면 스트링에 딱 맞게 공간을 할당하려면 세 스트링의 길이를

strlen() 함수로 구해서 모두 더한 값에 마지막 '\0' 문자에 대한 공간 하나를 추가해야 한다.

만약 strlen() 함수가 '\0'을 포함한 길이를 리턴하도록 구현됐다면 메모리 공간에 딱 맞게 계산하기가 번거롭다.

다음 코드는 방금 설명한 작업을 strcpy()와 strcat() 함수로 처리하는 예이다.

char* appendStrings(const char* str1, const char* str2, const char* str3)
{
	char* result = new char[strlen(str1) + strlen(str2) + strlen(str3) + 1];
	strcpy(result, str1);
	strcat(result, str2);
	strcat(result, str3);
	return result;
}

 

C와 C++에서 제공하는 sizeof() 연산자는 데이터 타입이나 변수의 크기를 구하는 데 사용된다.

예를 들어 sizeof(char)은 1을 리턴하는데, char의 크기가 1바이트이기 때문이다.

 

C 스타일 스트링에 적용할 때는 sizeof()와 strlen()의 결과가 전혀 다르다.

따라서 스트링의 길이를 구할 때는 절대로 sizeof()를 사용하면 안 된다.

sizeof()의 리턴 값은 C 스타일 스트링이 저장된 방식에 따라 다르기 때문이다.

스트링을 char[]로 저장하면 sizeof()는 '\0'을 포함하여 그 스트링에 대해 실제로 할당된 메모리 크기를 리턴한다.

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); // 플랫폼마다 다르다
size_t s4 = strlen(text2); // 6

이 코드를 32비트 모드에서 컴파일하면 s3의 값은 4고, 64비트 모드에서 컴파일하면 8이다.

sizeof()가 포인터 타입인 const char*의 크기를 리턴하기 때문이다.

 

C 스타일 스트링 연산에 관련된 함수는 모두 <cstring> 헤더 파일에 정의돼 있다.

strcpy()나 strcat은 컴파일러에서 보완 관련 경고나 에러 메시지가 출력될 수 있다.

경고가 나오지 않게 하려면 strcpy_s()나 strcat_s()와 같은 C 표준 라이브러리 함수를 사용하면 된다.

또한 프로텍트- 속성-C/C++-전처리기-전처리기 정의 칸에 _CRT_SECURE_NO_WARNINGS를 입력하면

strcpy를 써도 오류가 생기지 않는다.

'💻프로그래밍 내용 정리 > C++17' 카테고리의 다른 글

[C++ 2.1.3-1] C++std::string 클래스, 표준 사용저 정의 리터럴's'  (0) 2022.08.20
[C++ 2.1.2] 스트링 리터럴(리터럴 폴링, 로 스트링 리터럴, 확장 로스트링 리터럴)  (0) 2022.08.19
[C++ 1.6.4] 사용자 인터페이스  (0) 2022.08.19
[C++ 1.6.3] Database 클래스  (0) 2022.08.18
[C++ 1.6.2] Employee 클래스  (0) 2022.08.18
    '💻프로그래밍 내용 정리/C++17' 카테고리의 다른 글
    • [C++ 2.1.3-1] C++std::string 클래스, 표준 사용저 정의 리터럴's'
    • [C++ 2.1.2] 스트링 리터럴(리터럴 폴링, 로 스트링 리터럴, 확장 로스트링 리터럴)
    • [C++ 1.6.4] 사용자 인터페이스
    • [C++ 1.6.3] Database 클래스
    이이프
    이이프
    게임 프로그래머 지망생 / Since 2022.08.14

    티스토리툴바