[Cpp]동적 메모리 할당
📚동적 메모리 할당
어떤 프로그램이 실행되면 운영체제는 프로그램 실행을 위해 기억공간을 할당하게 되는데, 이때 할당되는 기억공간의 위치는 데이터, 힙, 스택 영역으로 나누어 볼 수 있습니다.
구분 | 설명 |
---|---|
데이터 영역 | 전역변수와 정적변수가 저장되는 영역 |
힙 영역 | 프로그래머의 필요에 의해 할당/소멸이 이루어지는 영역 |
스택 영역 | 지역변수와 매개변수가 저장되는 영역 |
동적 메모리 할당은 힙 영역을 이용하여 프로그램 실행 중에 입력되는 자료에 맞게 기억공간을 확보합니다. 하지만 동적 메모리 할당으로 생성된 저장공간은 이름이 없어 이름을 통해 접근할 수 없습니다.
따라서 이런 문제를 해결하기 위해 포인터를 사용합니다. 즉, 동적으로 할당된 저장공간을 포인터 변수가 가리키게 하여 접근할 수 있습니다.
📄new와 delete
동적 메모리 할당은 new 연산자를 이용합니다.
1
2
3
4
5
6
7
8
9
10
11
// 지정된 자료형의 데이터 1개를 저장할 수 있는 공간 할당
// 그 주소를 포인터 변수에 넣음
// 자료형은 포인터의 자료형과 일치해야 함
ptrVar = new TypeName;
// n은 양의 정수값을 내는 수식(상수가 아니어도 됨)
ptrVar = new TypeName[n];
// 메모리 공간 반환
delete ptrVar;
delete[] ptrVar;
예시
1
2
3
4
5
6
7
8
9
10
11
12
#include <iostream >
int main()
{
int* ptr;
ptr = new int;
*ptr = 1;
delete ptr;
ptr = nullptr;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <iostream>
int main()
{
int * ptr;
ptr = new int[3];
*ptr = 1;
*(ptr + 1) = 2;
ptr[2] = 3;
for (int i = 0; i < 3; ++i)
{
std::cout << ptr[i] << std::endl;
}
delete[] ptr;
ptr = nullptr;
}
📄포인터 연산
할당된 배열 공간에서 각각의 저장공간을 액세스하려면 포인터 연산을 이용하여 기준 위치의 포인터 값으로부터의 상대 위치를 지정합니다. 임의의 포인터 ptr을 기준으로 첫 번째 값의 주소는 ptr, 두 번째 값의 주소는 ptr+1, 세 번째 값의 주소는 ptr+2 등으로 표현합니다.
포인터의 실제 주소는 포인터가 어떤 자료형의 포인터인가에 따라 다릅니다. ptr이 100번지 부터 시작하는 int형 데이터를 가리키는 포인터라고 했을 때 ptr+1이 가리키는 주소는 104번지, ptr+2가 가리키는 주소는 108번지가 됩니다.
연산 | 처리 |
---|---|
ptr + n | ptr의 n번째 뒤의 저장공간에 대한 포인터 |
ptr - n | ptr의 n번째 앞의 저장공간에 대한 포인터 |
ptr++ | ptr 현재 위치의 다음 값을 가리킴 |
ptr– | ptr 현재 위치의 앞의 값을 가리킴 |
*(ptr + n) | ptr로부터 n번째 뒤에 저장된 값 |
*(ptr - n) | ptr로부터 n번째 앞에 저장된 값 |
*ptr++ 또는 *ptr– | *ptr의 값을 현재 수식에 사용하고 ptr이 다음 또는 이전 값을 가리킴 |
*++ptr 또는 *–ptr | 먼저 ptr이 다음 또는 이전 값을 가리키도록 한 후, 그 위치의 값을 수식에 사용 |
(ptr)++ 또는 (ptr)– | ptr이 가리키는 곳의 값을 현재 수식에 사용한 후 그곳의 값을 1 증가 또는 감소 |
++(ptr) 또는 –(ptr) | ptr이 가리키는 곳의 값을 1 증가 또는 감소시킨 후 그 값을 현재 수식에 사용 |
📄배열과 포인터
배열과 포인터는 매우 밀접한 관계에 있습니다. 배열의 이름은 배열의 첫 원소의 주소를 의미합니다. 이것은 포인터의 개념과 유사한데 배열변수는 포인터 변수가 아니므로 배열 이름이 가리키는 주소를 인위적으로 바꿀 수 없습니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include <iostream>
int main()
{
// 문자열의 끝을 알 수 있도록 널문자가 끝에 포함
char str[12] = "hello world";
char* ptr;
std::cout << str << std::endl;
// ptr이 배열 str을 가리킴(시작 주소)
ptr = str;
// 문자열의 끝이 아니면 반복
while (*ptr)
{
// 소문자인 경우 대문자로 바꿈
if (*ptr >= 'a' && *ptr <= 'z')
{
*ptr = *ptr - 'a' + 'A';
}
// 다음 문자로 포인터 이동
ptr++;
}
std::cout << str << std::endl;
}
Leave a comment