해결된 질문
작성
·
221
2
안녕하세요. 11강에서 질문을 드려야 했는데 이번 강의를 보고 한번 정리하고 가고자 질문을 드리게 되었습니다.
질문을 좀 더 자세하게 하기 위해 메모리 레이아웃 사진첨부를 하였습니다.
const char* str = “Constant string”; // str is a modifiable lvalue.
str = “Second string”; // “Constant string” = “Second String” // imposible
str[0] = ‘A’; //Error
char str2[] = “String in an array”;
str2[0] = ‘A’; // OK
이번 강의에서 나온 코드를 가지고 개념 정리를 하고 싶습니다.
코드에 쓰인 문자열은 어디에 저장이 되는가?
이번 강의에서 쓰인 문자열 포인터
char* str = “Constant string”
str = “Second string”
그리고 문자열 배열
char str2[] = “String in an array”
여기에 쓰인 모든 문자열 “Constant string”, “Second string”, “String in an array” 은 TEXT Segment 즉 프로그램 코드에 저장이 되는 걸로 알고있습니다. 맞을까요?
문자열 포인터와 문자열 배열의 차이
문자열 포인터는 TEXT Segment에 저장되어 있는 문자열의 메모리 주소를 가리키는 것이다. 즉 읽기 전용에 저장되어 있기 때문에 str[0] = 'A'와 같이 수정하려 하면 OS에서 막는다.
이걸 VS에서 디버깅으로 확인을 해보았습니다.
먼저 const char* str = “Constant string”;을 확인 해보았습니다. str 포인터 변수가 가리키고 있는 메모리 주소를 메모리에서 찾아 보았습니다.
검색을 해보니 문자열의 시작 문자 'C'의 메모리 주소를 가리키고 있으며 문자열의 끝인 g 다음엔 \0이 붙어있는 걸 확인할 수 있었습니다.
여기서 str = “Second string”; 구문을 만난다면
str 포인터 변수가 가리키고 있는 메모리 주소가 문자열의 시작 문자'S'의 메모리 주소를 가리키고 있는걸 확인하였습니다. 그리고 문자열의 끝인 g옆에는 \0이 붙어있는걸 확인할 수 있었습니다. 그럼 여기서 문자열 배열은 어떤 식이냐
일단 문자열 포인터와 문자열 배열에서 사용한 문자열들은 TEXT Segment에 저장이 되어있기 때문에 메모리에서 보면 사용한 문자열들이 나란히 있는 걸 확인할 수 있었습니다. 하지만 디버깅을 통해 현재 문자열 배열인 str2[]의 메모리 주소를 보면
인걸 확인할 수 있었습니다. 분명 저 문자열이 저장되어 있는 메모리 주소 : 0x00007FF648499C10 이랑 전혀 틀린 주소입니다.
검색해보면 똑같은 문자열이 해당 메모리 주소에도 있는걸 확인하였습니다.
위와 같은 내용을 통해 알수 있었던 것은 프로그램 만들때 사용한 모든 문자열은 TEXT Segment(읽기전용)에 저장이 되며 문자열 포인터는 TEXT Segment에 있는 "문자"의 메모리 주소를 가리키는 것이며 문자열 배열은 스택이라는 (읽기, 쓰기전용)메모리 공간을 할당받고 TEXT Segment에서 문자열들을 복사해오기 때문에 str2[0] = 'B' 같은 수정이 가능한 것이다. 라고 이해를 하였는데 제대로 이해한게 맞을까요?
마지막으로 문자열 포인터를 사용하는 이유?
마지막 질문은 제가 생각을 해보았습니다. 수정도 못하는 문자열 포인터는 왜 사용할까? 생각을 해보았는데 프로그램을 보면 분명 수정이 필요없는 고정된 문자열들을 본적이 있습니다.그런것들을 사용할 때 불필요하게 TEXT Segment에 저장이 되었다가 스택 메모리를 할당 받고 데이터를 "복사"해서 사용하면 메모리 낭비가 일어나고 어떤 행위를 하는 것 이기 때문에 불필요한 과정을 하기 때문에 이런 것들은 그냥 TEXT Segment에 저장 되어있는 문자열의 주소를 가리켜서 사용하면 메모리 절약을 할 수 있는 관점에서 사용하는 것 일까요?
답변 2
2
안녕하세요, 질문&답변 도우미 Soobak 입니다.
질문 1) 문자열 리터럴이 저장되는 곳
: 네, 맞습니다.“Constant string”
등의 문자열 리터럴은 TEXT Segment 에 저장되며, 프로그램 코드와 함께 읽기 전용 메모리에 위치합니다.
질문 2) 문자열 포인터와 문자열 배열의 차이, 그리고 데이터 복사 과정
: 네, 말씀하신 내용이 맞습니다.
문자열 배열 char str2[] = "String in an array";
이 선언될 때, 스택(또는 전역/정적 변수인 경우 DATA Segement)에 메모리를 할당 받고, 문자열 리터럴의 내용이 이 배열로 복사됩니다.
따라서, 읽기 및 쓰기가 가능해지고 str2[0] = 'A';
와 같은 수정이 가능합니다.
질문 3) 문자열 포인터의 사용 이유
: 네, 맞습니다.
수정할 필요가 없는 고정된 문자열에 대해서, 프로그램 내에서 사용할 때 마다 메모리에 복사하여 사용하면 메모리 사용량이 불필요하게 증가하게 됩니다. 따라서, 읽기 전용의 문자열 리터럴에 대한 참조로서 문자열 포인터를 사용하는 것을 통해 메모리를 효율적으로 관리하게 됩니다.
모두 잘 이해하고 계신 것 같습니다!
0
안녕하세요, 인프런 AI 인턴입니다. 김민수님의 질문에 대해 답변을 도와드리겠습니다.
제공된 답변 중에서 문자열이 메모리에 저장되는 위치와 관련된 부분은 다음 답변에서 확인하실 수 있습니다:
질문자님이 올리신 이미지 내용을 바탕으로 요약해보자면 이렇습니다:
문자열 리터럴, 예를 들어 "Constant string"
과 같은 문자열은 텍스트 세그먼트(TEXT Segment) 또는 읽기 전용 데이터 세그먼트에 저장됩니다. 이는 컴파일러 또는 운영체제의 구현에 따라 달라질 수 있으며, 대부분 읽기 전용입니다.
문자열 포인터(예: const char* str = "Constant string";
)는 이러한 텍스트 세그먼트의 주소를 가리킵니다. 따라서 문자열 포인터로 해당 문자열을 수정할 수 없으며, 포인터 자체는 수정할 수 있습니다(가리키는 주소를 변경할 수 있음).
문자열 배열(예: char str2[] = "String in an array";
)은 배열의 크기에 따라 스택이나 데이터 세그먼트와 같은 읽고 쓸 수 있는 메모리 영역에 문자열 리터럴을 복사해 넣습니다. 이렇게 복사된 문자열은 수정이 가능합니다.
문자열 포인터를 사용하는 이유는 수정이 필요 없는 고정된 문자열을 효율적으로 사용하기 위함입니다. 문자열 포인터를 사용하면 스택이나 데이터 세그먼트에 복사하지 않고도 문자열 리터럴을 참조할 수 있어 메모리 사용과 처리 과정 측면에서 효율적입니다.
질문하신 내용이 맞으며, 제대로 이해하신 것으로 보입니다.
저는 질문자님의 이해를 돕고자 지식공유자님의 기존 답변을 참고하여 유사한 답변 링크를 추천해드리고 있습니다.
현재 베타 기능으로 답변이 만족스럽지 않을 수 있는 점 양해 부탁드립니다. 🙏
추가적으로 궁금한 점이 있으시면, 이어서 질문해 주세요. 곧 지식공유자께서 답변해 주실 것입니다.