포인터 변수는 컴퓨터 메모리의 주소를 저장하기 위한 저장공간(변수)으로 변수가 저장되는 메모리와 관계가 있다. 프로그래머가 프로그램에서 변수를 선언한다는 것은 컴퓨터 메모리에 변수의 자료형에 해당하는 데이터를 저장하기 위한 저장공간을 할당하는 것이다. 컴퓨터 메모리의 저장공간은 바이트 단위로 주소(메모리 주소)를 부여하여 저장공간을 식별한다. 새로운 데이터를 저장하기 위해서 변수를 선언하면 메모리에 자료형에 해당되는 저장공간이 할당된다. 이와 같이 할당된 변수의 저장공간의 주소를 포인터 변수에 저장할 수 있다. 포인터 변수는 이러한 메모리 주소를 저장하기 위해 사용되는 변수로 포인터라고도 한다.
#include <iostream>
using namespace std;
int main(int argc, char const *argv[])
{
int a = 10; // (1) 일반 변수 선언 및 데이터 값으로 초기화
int* ptr = NULL; // (2) 포인터 변수 선언 및 NULL 값으로 초기화
// 변수 a를 위해 할당된 메모리 공간의 시작 주소 출력
cout << "변수 a를 위해 할당된 메모리 주소: " << &a << endl;
ptr = &a; // (3) a의 메모리 주소를 포인터 변수 ptr 에 저장
// 변수 ptr에 저장된 주소 값에 저장된 데이터 값 출력
cout << "ptr 이 가리키는 곳에 저장된 데이터 값(*ptr): " << *ptr << endl;
cout << "변수 a에 저장된 값: " << a << endl;
*ptr = 30; // (4) ptr을 이용하여 메모리 공간에 데이터 값 대입
// ptr에 저장된 주소 갑 확인
cout << "ptr에 저장된 주소 겂(ptr): " << ptr << endl;
// 변수 a에 저장된 값 확인
cout << "ptr을 이용한 데이터 값 조작 후 변수 a의 값(a): " << a << endl;
return 0;
}실행 결과는 다음과 같다.
변수 a를 위해 할당된 메모리 주소: 0x16fb536fc
ptr 이 가리키는 곳에 저장된 데이터 값(*ptr): 10
변수 a에 저장된 값: 10
ptr에 저장된 주소 겂(ptr): 0x16fb536fc
ptr을 이용한 데이터 값 조작 후 변수 a의 값(a): 30다음 동영상은 일반 변수와 포인터 변수가 메모리에 할당된 공간에 저장된 값의 변화를 나타낸다.
포인터 변수는 컴퓨터 메모리에 저장된 데이터를 변수 이름이 아닌 주소로 직접 접근할 때 사용하며, 일반적으로 메모리의 특정 주소를 접근할때 사용한다.
포인터 변수는 주소를 저장하는 변수로 일반 변수의 주소를 저장할 수 있는 변수이다. 주소를 저장하는 저장공간을 할당하기 위해서는 일반 변수와 같이
포인터 변수가 선언되어야 한다. 포인터 변수 선언은 일반 변수 선언과 구별하기 위해서 자료형과 변수명 사이에 * 기호를 사용한다.
포인터 변수를 선언할 때 자료형을 함께 명시하는 이유는 포인터 변수에 저장된 주소로부터 자료형에 해당되는 바이트 수 만큼 저장공간을 참조해야 하기 때문이다.
일반적인 PC환경에서 char형 변수는 1바이트, short형 변수는 2바이트, int형 변수는 4바이트, double형 변수는 8바이트의 메모리 공간을 차지한다. 그러므로 char형 포인터 변수는 저장된 주소 1 바이트, short형 포인터 변수는 저장된 주소로 부터 2바이트, int형 표인터 변수는 저장된 주소로 부터 4바이트, double형 포인터 변수는 저장된 주소로 부터 8바이트의 데이터를 고려하여야 한다.
일반적인 포인터 변수의 선언은 다음과 같다.
<자료형>* <변수이름>int형 자료형 포인터 변수 ptr 선언은 다음과 같이 한다. 포인터 변수 ptr에는 실 데이터가 저장된 메모리의 저장공간의 주소가 저정되지 않았다.
int* ptr;다음 코드는 int형 일반 변수 value와 포인터 변수 iptr을 선언한 후, 포인터 변수 iptr에 일반 변수 value를 위해
할당된 4바이트의 저장 공간 중 첫 주소가 저장된다. int형 포인터 변수는 int형의 데이터가 저장된 저장공간의 주소 만을 저장해야 한다.
char형의 데이터 저장공간의 주소를 저장하기 위해서는 char형 포인터 변수를 선언하여야 한다.
int value;
int* iptr;
iptr = &value;- 메모리 주소 관련 연산자
| 연산자 | 의미 | 피연산자 (연산자를 적용가능한 변수) |
|---|---|---|
| & | :변수가 저장될 메모리의 주소를 얻는 연산자 (주소연산자) | 일반 변수 및 포인터 변수 |
| * | 메모리 주소 값에 저장된 데이터 값을 얻는 연산자 (간접 참조 연산자, 역참조 연산자) | 포인터 변수 |
- 여러 개의 포인터 변수를 선언할 때는 다음과 같이 작성하여야 한다.
int *p, *q, *r; // p, q, r 모두 포인터 변수
int* p, q, r; // p는 포인터 변수, q, r 은 일반 변수 - 포인터 변수는 다음과 같이 여러 자료형으로 선언이 가능하다.
char* pc; // char형의 데이터가 저장된 메모리 주소를 저장하기 위한 포인터 변수 (pc)
int* pi; // int형의 데이터가 저장된 메모리 주소를 저장하기 위한 포인터 변수 (pi)
float* pf; // float형의 데이터가 저장된 메모리 주소를 저장하기 위한 포인터 변수 (pf)
double* pd; // double형의 데이터가 저장된 메모리 주소를 저장하기 위한 포인터 변수 (pd)
void* p; // 메모리에 저장된 데이터에 관계없이 주소를 저장할 수 있는 포인터 변수 (p)
Car* pobj; // Car 클래스의 객체가 저장된 메모리 주소를 저장하기 위한 포인터 변수 (pobj)
void (*f)(double); // 함수 포인터 (매개 변수가 더블인 반환 자료형이 잆는 함수 주소)void 자료형의 포인터 변수 p (void* p) 는 자료형이 규정되어 있지 않는 것으로 저장된 데이터의 자료형에 따라 다른 자료형의 포인터 변수에 대입할 수 있다.
pf = (float *)p;포인터 변수에 저장된 메모리 주소에 저장된 값을 읽거나 변경하는 것이 가능하다. 포인터 변수 ptr에 저장된 메모리 주소에 저장된 데이터 값을 얻기 위해서는
*연산자를 다음과 같이 포인터 변수 ptr 앞에 붙여서 *ptr 와 같이 작성하면 ptr 변수에 저장된 주소 값에 저장된 데이터 값을 뜻한다.
* 연산자는 포인터 변수를 통해 데이터를 간접 참조(deferencing, indirection)한다고 한다.
변수 선언 시 사용하는 *은 연산자가 아니라 선언하는 변수가 일반 변수가 아니라 포인터 변수라는 것을 명시하기 위해서 사용되는 기호이다.
포인터 변수가 선언된 후 포인터 변수 앞에 사용되는 *는 기호가 아니라 간접 참조 연산자이다.
* 연산자는 단항 연산자로 괄호 다음으로 높은 우선순위를 가진다. 따라서 다른 연산자보다 먼저 실행된다.
int value - 100;
int *iptr;
iptr = &value;
cout << "value의 값: " << *iptr << endl;앞의 프로그램의 실행 결과는 다음과 같다.
value의 값: 100