메모리 구조
편집C와 C++에서 메모리는 다음과 같은 모습으로 나타내어집니다.
스택
지역 변수가 쌓입니다. stack은 쌓아 올린 무언가를 뜻합니다. |
힙
프로그래머가 운영체제에 요청하여 사용할 수 있는 자유 공간입니다. |
BSS(Block Started by Symbol)
정의만 이루어진, 전역변수와 static 변수가 들어갑니다. |
데이타
정의와 초기화가 동시에 이루어진, 전역변수와 static변수가 들어갑니다. |
코드
컴파일러에 의해 기계어(바이너리)로 만들어진 코드가 들어갑니다 |
주의하세요! |
위 구조를 메모리 맵이라고 부릅니다. 위의 구조는 단순화, 일반화한 모습입니다. 실제 메모리 맵은 사용하는 프로그래밍 언어에 따라, cpu에 따라, 동작 환경에 따라 달라질 수 있습니다. |
이 중에서 우리가 관심 가져야 할 영역은 힙(heap)입니다. 우선 다음 소스를 봅시다.
6.01 문자열을 입력받아 대소문자를 바꿔줍니다 |
---|
#include <iostream>
using namespace std;
int main(void)
{
char input[10]={};
int index = 0;
cin>>input;
while(input[index]!='\0')
{
if(input[index]>='A' && input[index]<='Z')
input[index]+=32;
else if(input[index]>='a' && input[index]<='b')
input[index]-=32;
index++;
}
cout<<input<<endl;
return 0;
}
|
abcDEF!@# ABCdef!@# |
소문자 abc는 대문자인 ABC로 바뀌었고 대문자 DEF는 소문자 def로 바뀌었으며, 특수문자인 !@#는 알파벳이 아니니 입력한 모습 그대로 출력되었습니다.
그런데 학습자 당신에게 이런 불평이 들려왔다고 합시다.
이 프로그램은 겨우 9글자밖에 입력할 수 없어요. 난 더 길게 입력하고 싶어요!
그래서 당신은 흔쾌히 소스를 수정해 더 많이 입력할 수 있는 프로그램을 만들어 주었습니다. 마치 다음 소스처럼요.
6.02 문자열을 입력받아 대소문자를 바꿔줍니다. 99글자까지 지원! |
---|
#include <iostream>
using namespace std;
int main(void)
{
char input[100]={};
int index = 0;
cin>>input;
while(input[index]!='\0')
{
if(input[index]>='A' && input[index]<='Z')
input[index]+=32;
else if(input[index]>='a' && input[index]<='b')
input[index]-=32;
index++;
}
cout<<input<<endl;
return 0;
}
|
abcdefgHIJKLMN!@#$%^& ABCDEFGhijklmn!@#$%^& |
잘 작동 되는 것 같습니다. 하지만 아직도 당신에게 불평할 사람이 있는 것 같습니다.
전 대부분의 99자보다 적게 입력해요. 하지만 어쩌다가 어쩌다가 1,000자, 10,000자, 일년에 한번쯤은 100,000,000자를 입력할 때도 있어요.
이렇게 많은 글자도 입력할 수 있게 해주세요.
어떻게 해야할까요? char input[100000000]={}으로 소스를 변경해야 할까요? 하지만 이 사용자는 대부분의 경우 99자보다 적게 입력한다고 합니다. 일년의 한번을 위해서 항상 프로그램이 sizeof(char)*100000000만큼을 할당 받게 하는 건 엄청난 낭비입니다.
이러한 문제를 해결하기 위해서, C언어는 실행되기 전에 크기를 정하지 않고, 실행 중에 필요에 따라 자유롭게 할당할 장소를 제공해줍니다.
그곳의 이름이 바로 힙입니다.
T I P |
C에서는 힙을 위해 malloc함수를 사용합니다. C++에서도 <cstdlib>를 include함으로서 malloc함수를 사용할 수 있습니다. 다만 C++에서는 void*의 암묵적 형변환이 불가능하기 때문에 할당한 공간 주소를 명시적 형변환하여 사용해야 합니다. |
new & delete
편집C++에서 힙 영역에 원하는 만큼 메모리를 할당받기 위해서는(다시 말해서, 원하는 크기의 변수를 힙에 선언하기 위해서는) new라는 명령어를 사용면 됩니다.
다음과 같이 사용하면 됩니다.
int new_data = new int
배열은 다음과 같이 할당 시키면 됩니다.
int * new_data = new int[10]
사용이 끝난 동적 할당 공간은 다음과 같이 삭제합니다.
delete new_data;
사용이 끝난 동적 할당 배열 공간은 다음과 같이 삭제합니다.
delete[] new_data
주석을 참고하면서 다음 소스를 읽어보세요.
6.03 new맛 보기 |
---|
#include <iostream>
#include <cstring>
using namespace std;
int main(void)
{
char *input= new char[5];
char *new_input;
int index = 0;
int max_index = 4; // 배열의 크기를 나타냅니다
//인덱스는 0부터, 크기는 1부터 시작하니, max_index+1이 실제 크기겠죠?
while(true)
{
cin>>input[index];
if(index >= max_index) // 만약 배열을 다 썼다면
{
new_input = new char[max_index+=1+5]; // 현재보다 5칸을 늘려서 new_input이 가리키게 하고
strcpy(new_input, input); // 지금까지 내용을 새로운 공간에 복사해 넣고
delete[] input; // 예전 공간을 지우고
input = new_input; // input을 이제 새 공간을 가리키게 합니다
}
if((int)input[index]==26) // CTRL + Z가 ascii코드로 26입니다
{input[index]='\0'; break;} // CTRL + Z를 입력하면 널 문자를 집어넣고 while문을 나갑니다
index++:
}
cout<<input<<endl;
delete[] input;
return 0;
}
|
zxcvsafasfwqerasfasdfxzvxcvzqwasfsafqwer^z zxcvsafasfwqerasfasdfxzvxcvzqwasfsafqwer |
new와 delete는 문법적으론 어렵지 않습니다. 여러번 사용하여 익히도록 합시다.
예제 6.01번 |
동적할당으로 문자를 입력 받습니다. 소문자는 대문자로, 대문자는 소문자로 바꿔서 출력하도록 합시다. CTRL+Z를 입력하면 입력이 종료되도록 합니다. |
연습 문제 6.01번 |
동적 할당으로 문자열을 입력 받습니다. 한 문자열과 다른 문자열은 공백(space)으로 구분됩니다. CTRL+Z를 입력받으면 입력이 종료되도록 합니다. 출력 형태는 다음과 같습니다. [1번 문자열]hello 이 문제는 어려운 문제이고, 여러가지 답변이 가능합니다. 시간을 들이면서 찬찬히 풀어봅시다. |
정리
편집무엇을 배웠는지 기억해봅시다. 복습은 최고의 공부법!
- 메모리 맵의 형태를 생각해봅시다.
- 실행 중에 크기를 결정해 마음대로 공간을 할당할 수 있는 곳의 이름은?
- 그래서, 그곳에 공간 할당하기 위해서 어떤 명령어를 썼나요.
- 지우기 위해서는?
- 배열 공간을 만들고, 지울때는 조금 달랐습니다. 어떻게 달랐는지 생각해 보세요.