#13. 포인터
#포인터
포인터도 변수의 일종이다.
다른 변수의 주소값을 저장할 수 있는 변수이다.
일반 변수 앞에 어드레스 연산자인 '&'를 붙이면 해당 변수의 주소가 표현된다.
#include <iostream>
using namespace std;
int main()
{
int i = 1;
cout << &i << endl; // i변수의 주소값 출력
}
포인터는 일반적으로
자료형* 변수명;
으로 선언한다.
선언을 할 때 주의점은 단순히 ex) int* ptr; 이런식으로 선언할 시 ptr에 쓰레기값이 들어가게 되기 때문에, 어느 주소가 들어가있는지 모르기 때문에 그 데이터를 수정하게 될 경우 심각한 오류가 발생할 수 있다.
이렇게 선언된 포인터 변수에는 다른 변수의 주소값이 들어갈 수 있다.
#include <iostream>
using namespace std;
int main()
{
int i = 10;
cout << &i << endl; // i변수의 주소값 출력
int* ptr = nullptr; // 포인터는 일반적으로 0,NULL,nullptr 로 초기화 해준다.
ptr = &i; // 포인터 변수 ptr에 i변수의 주소값을 입력
cout << ptr << endl; // ptr 출력
}
i변수의 주소값 출력과 그 주소값을 포인터 변수에 대입하고 포인터변수를 출력한 결과이다.
정상적으로 i변수의 메모리주소 00DFF9C0가 출력되었으며,
그 주소값이 ptr포인터 변수에 들어가고 출력 또한 정상적으로 이루어 졌다.
이때, 역참조 연산자라는 '*'을 변수 앞에 붙여주면 해당 주소에 있는 값이 무엇인지 확인 할 수 있다.
#include <iostream>
using namespace std;
int main()
{
int i = 10;
int* ptr = nullptr; // 포인터는 일반적으로 0,NULL,nullptr 로 초기화 해준다.
ptr = &i; // 포인터 변수 ptr에 i변수의 주소값을 입력
cout <<"&i: "<< &i << endl;
cout << "ptr: " << ptr << endl; // ptr 출력
cout << "*&i: " << *&i << endl; // 역참조 연산자 확인
cout << "*ptr: " << *ptr << endl;
}
이와같이 포인터는 변수의 주소를 저장할 수 있고, 역참조 연산자인 *을 사용하여 해당 주소에 어떤 값이 있는지 확인 할 수 있으며, 또한 수정이 가능하다.
해당 주소값만 있으면 한 함수 내에 있는 변수가 아니라 하더라도 직접 access 하여 수정 변환 할 수 있으며, 이 활용도는 어마어마하다.
#include <iostream>
using namespace std;
int main()
{
int i = 10;
int* ptr = nullptr;
ptr = &i; // ptr에 i변수의 주소값이 들어감
cout << i << endl;
*ptr = 5; // ptr에서 가르키는 주소값을 찾아간뒤 값을 5로 변경
cout << i << endl;
}
위를 확인해보면 포인터로 직접 i에 access 하여 i값을 수정할 수 있다.
이는 같은 main 함수가 아니라 따로 함수를 만들어도 거기서 i의 주소값만 받는다면 언제든지 접근할 수 있다.
※주의점
포인터 변수는 32bit 환경에서 4byte로 크기가 동일하지만
(이유는 최대 메모리 크기의 주소를 4bytes로 모두 표현할 수 있기 때문)
포인터 변수의 자료형은 해당 주소값의 자료형이랑 동일해야한다.
(이유는 해당 주소값을 찾아간 뒤에 int형만큼 읽어라 라는 뜻인데, 자료형이 다르면 불가능 하기 때문)
ex)
int i=1;
int* ptr = &i;
-> ok!
long i=1;
int* ptr = &i;
-> X