C++에서 포인터(Pointer)는 매우 중요한 개념으로, 변수나 데이터의 메모리 주소를 저장하는 변수입니다. 포인터를 사용하면 메모리의 효율적인 관리가 가능하고, 동적 메모리 할당과 같은 고급 기능을 사용할 수 있습니다.
포인터의 구조와 사용법에 대해 자세히 설명하겠습니다.
1. 포인터의 기본 개념
포인터는 변수의 메모리 주소를 저장하는 변수입니다. C++에서 변수는 메모리 상에 데이터를 저장하는 공간을 가지고 있는데, 포인터는 그 주소를 저장합니다.
포인터의 구조:
- 포인터는 * 연산자를 사용하여 선언하며, 이는 해당 변수는 주소를 가리킨다는 의미입니다.
- 포인터는 특정 타입의 변수만을 가리킬 수 있습니다. 예를 들어, int 타입 포인터는 int 변수의 메모리 주소만 가리킬 수 있습니다.
설명:
- &x는 변수 x의 메모리 주소를 반환합니다.
- ptr는 x의 메모리 주소를 저장하는 포인터입니다.
- ptr을 사용하여 x의 값을 간접적으로 접근할 수 있습니다.
2. 포인터 선언 및 사용
포인터는 타입과 함께 선언됩니다. 예를 들어, int* ptr은 int 타입을 가리키는 포인터입니다. 이를 통해 변수의 메모리 주소를 저장하고, 그 주소를 통해 변수에 접근할 수 있습니다.
포인터 선언
포인터 사용 예시
#include <iostream>
using namespace std;
int main() {
int a = 5; // 일반적인 정수형 변수
int* ptr = &a; // a의 주소를 ptr에 저장 (포인터 선언)
cout << "a의 값: " << a << endl; // a의 값 출력
cout << "ptr이 가리키는 값: " << *ptr << endl; // ptr이 가리키는 값을 출력 (간접 참조)
cout << "a의 주소: " << &a << endl; // a의 주소 출력
cout << "ptr의 값 (주소): " << ptr << endl; // ptr이 저장한 주소 출력
return 0;
}
설명:
- &a: a의 메모리 주소를 가져옵니다.
- *ptr: ptr이 가리키는 주소에 저장된 값을 간접적으로 참조합니다.
- *ptr은 포인터 ptr이 가리키는 위치의 값을 반환합니다.
3. 간접 참조 (Dereferencing)
간접 참조는 포인터가 가리키는 메모리 주소에 저장된 값을 읽거나 수정하는 과정입니다. * 연산자는 포인터를 통해 간접적으로 변수에 접근할 때 사용됩니다.
예시: 간접 참조
#include <iostream>
using namespace std;
int main() {
int num = 100;
int* ptr = #
// 포인터를 통해 간접적으로 값 변경
*ptr = 200; // ptr이 가리키는 값 변경 -> num의 값이 200로 변경
cout << "num의 값: " << num << endl; // 200 출력
return 0;
}
설명:
- *ptr = 200;는 ptr이 가리키는 num 변수의 값을 200으로 변경합니다. 즉, num의 값은 200으로 업데이트됩니다.
4. 포인터와 배열
배열의 이름은 배열의 첫 번째 요소의 주소를 가리키는 포인터로 취급됩니다. 따라서 배열을 포인터처럼 다룰 수 있습니다.
배열과 포인터
#include <iostream>
using namespace std;
int main() {
int arr[] = {10, 20, 30, 40, 50};
int* ptr = arr; // 배열의 첫 번째 요소의 주소를 포인터 ptr에 저장
// 배열 원소를 포인터를 통해 접근
for (int i = 0; i < 5; i++) {
cout << "arr[" << i << "] = " << *(ptr + i) << endl; // ptr + i는 배열 요소의 주소
}
return 0;
}
설명:
- arr은 배열의 첫 번째 요소의 주소를 가지고 있습니다. 따라서 ptr을 배열처럼 사용할 수 있습니다.
- *(ptr + i)는 배열의 각 요소에 접근하는 방식입니다. ptr + i는 ptr에서 i만큼 떨어진 메모리 주소를 의미합니다.
5. 포인터의 크기
포인터 변수의 크기는 포인터가 가리키는 데이터 타입에 상관없이 주소 크기와 동일합니다. 보통 64비트 시스템에서는 8바이트입니다.
#include <iostream>
using namespace std;
int main() {
int* ptr;
double* ptr2;
cout << "int 포인터 크기: " << sizeof(ptr) << " 바이트" << endl; // 보통 4바이트 또는 8바이트
cout << "double 포인터 크기: " << sizeof(ptr2) << " 바이트" << endl; // 보통 4바이트 또는 8바이트
return 0;
}
설명:
- sizeof(ptr)는 포인터가 가리키는 타입의 크기와 관계없이 포인터 자체의 크기를 반환합니다. 포인터는 메모리 주소를 저장하므로, 포인터의 크기는 시스템의 아키텍처에 따라 다를 수 있습니다.
6. 포인터와 동적 메모리 할당
C++에서는 new와 delete 연산자를 사용하여 동적 메모리 할당 및 메모리 해제를 할 수 있습니다.
예시: 동적 메모리 할당
#include <iostream>
using namespace std;
int main() {
int* ptr = new int; // 동적 메모리 할당
*ptr = 50; // 할당된 메모리에 값 대입
cout << "동적 할당된 값: " << *ptr << endl; // 50 출력
delete ptr; // 동적 메모리 해제
return 0;
}
설명:
- new int는 int 타입을 위한 메모리 공간을 동적으로 할당합니다.
- delete ptr은 동적으로 할당한 메모리를 해제합니다. 메모리 누수를 방지하기 위해 delete를 사용하여 할당한 메모리를 반드시 해제해야 합니다.
7. 포인터 배열
포인터 배열은 여러 개의 포인터를 저장할 수 있는 배열입니다. 예를 들어, 문자열을 가리키는 포인터들의 배열을 만들 수 있습니다.
예시: 포인터 배열
#include <iostream>
using namespace std;
int main() {
const char* fruits[] = {"Apple", "Banana", "Cherry"};
for (int i = 0; i < 3; i++) {
cout << fruits[i] << endl; // Apple, Banana, Cherry 출력
}
return 0;
}
설명:
- fruits는 문자열을 가리키는 포인터의 배열입니다. 각 포인터는 문자열을 가리킵니다.
8. 포인터와 함수
함수에 포인터를 전달하여 값의 변경을 반영하거나, 함수의 반환 값으로 포인터를 반환할 수 있습니다.
예시: 포인터를 함수 매개변수로 전달
#include <iostream>
using namespace std;
void changeValue(int* ptr) {
*ptr = 100; // 포인터가 가리키는 값 변경
}
int main() {
int num = 10;
cout << "변경 전 값: " << num << endl; // 10 출력
changeValue(&num); // 포인터로 값을 변경
cout << "변경 후 값: " << num << endl; // 100 출력
return 0;
}
설명:
- changeValue 함수는 int 타입의 포인터를 매개변수로 받습니다. 함수 내부에서 *ptr을 통해 값을 변경합니다.
'IT' 카테고리의 다른 글
[게임프로그래머 전망] 5년동안 경험과 연봉에 대한 정보 (0) | 2022.12.19 |
---|---|
[랜섬웨어 바이러스] 방지하는 방법과 감염경로는? (0) | 2022.08.31 |
[파일 시스템 오류] -2147416359 이미지 파일 실행 오류 해결방법 (0) | 2022.08.28 |
[아이폰 14] 출시일과 가격 그리고 사전예약은? (2) | 2022.08.25 |
[메타버스 전망] 뜻과 의미 그리고 관련된 산업은? (1) | 2021.10.07 |