본문 바로가기

교육 노트/C++ 기초강의

[C++ 때려잡기] C++ 기초강의 4-3 마침내 포인터, 포인터 기초

2018/08/26 - [교육 노트/C++ 기초강의] - [C++ 때려 잡기] C++ 기초강의 4-1 간단한 구조체

2018/08/26 - [교육 노트/C++ 기초강의] - [C++ 때려 잡기] C++ 기초강의 4-2 배열과 다중배열


이번강의는 포인터이다.


포인터를 처음에는 이해하기 어려워하지만 알고 보면 어렵지않다.





1. 포인터란?




라고 한다.


아니 이게 무슨소리냐고?






포인터란

한마디로 주소값을 저장하는 자료형이다

다시 말하자면 주소값을 저장하는 자료형이다

또 다시 말하자면 주소값을 저장하는 자료형이다


즉 포인터는 주소값을 저장하는 자료형이다


그림으로 살펴보면



즉 여기서는 포인터가 메모리의 주소값 1004를 저장하고있는 자료형이 되는것이다.

또한 그 주소에 가면 저장된 값이 int 형식이므로 int형 포인터이다.



이름이 포인터인 이유는




그냥 해당값을 가지고있는 주소값을 가지고있으니 메모리의 위치를 가르키고 있는것이고 따라서 포인터란 이름이 붙었다


조금 다른 개념이지만 쉽게 설명하자면

naver 웹사이트 자체가 value이고 naver의 주소 https://www.naver.com/ 가 포인터라고 생각하면된다.



포인터의 개념은 이것이 끝이다.



그럼 사용법을 알아보자



포인터 선언은 다음과 같다





계속 말했듯이 포인터는 자료형이기 때문에 number_ptr의 자료형은 인트 포인터형 변수이다

참고로 이렇게 이미있는 자료형에서 유도되는 새로운 자료형을 유도형 자료형이라고 한다.



자 그러면 포인터 변수를 만들었으니 사용해야하는데

사용하기 전에 앞서 알아야할 연산자가 있다.


2. & 연산자, * 연산자



우선 해당 변수가 저장된 주소값을 알려주는 & 연산자 이다. 레퍼런스의 &과 동일하나 &는 자료형에 붙으면 레퍼런스 자료형이란 의미이고 만들어진 변수의 이름앞에 붙으면 해당 변수의 주소값을 나타내는 어드레스 오브 연산자이다.



다음은 * 연산자 이다

* 연산자는 주소값 앞에 붙어 해당 주소값에 있는 값을 나타내는 연산자이다 역시 자료형에 붙으면 포인터 변수 자료형이라는 의미이고 주소값 앞에 붙으면 해당 주소값의 값을 나타내는 벨류 오브 연산자이다


당연하게 *과 &는 역 연산 관계이다





3. 포인터 사용


자 이제 그러면 변수의 주소값과 주소값의 값을 자유롭게 다룰수있으니 포인터를 사용해보자







이렇게 되면 x_ptr은 변수 x가 저장된 주소값을 가지게 될것이다

따라서 x_ptr을 출력하면 x의 주소값이 1000이 나올것이고

x_ptr이 가르치는 값인 *(x_ptr)을 출력하면 주소값 1000에 저장된 값인 10 이 나올것이다.



#include <iostream>
#include <ctime>
using namespace std;

int main()
{
  int x = 10;
  int* x_ptr;
  x_ptr = &x;

  cout << "X값:" << x << endl;
  cout << "X의 주소값:" << &x << endl;
  cout << "X_ptr의 값:" << x_ptr << endl;
  cout << "X_ptr이 가르키는값:" << *x_ptr << endl;
  return 0;
}



다음과 같은결과를 확일할수있다.


주소값에 알파벳이 섞여있는이유는 주소값은 기본적으로 HEX 표기법을 따르기 때문이다.


10진법 숫자로 표현하기 위해 주소값은 int로 형변화 해보면



#include <iostream>
#include <ctime>
using namespace std;

int main()
{
  int x = 10;
  int* x_ptr;
  x_ptr = &x;

  cout << "X값:" << x << endl;
  cout << "X의 주소값:" << (int)&x << endl;
  cout << "X_ptr의 값:" << x_ptr << endl;
  cout << "X_ptr이 가르키는값:" << *x_ptr << endl;
  return 0;
}





10진법으로 나타낸 x의 주소와 16진법인 x_ptr의 값이 사실상 같음을 알수있다.





4. 포인터 산술연산



x_ptr+1은 x_ptr이 int형 포인터기때문에 값에 4를 더한 1004가 된다.

만약 double 포인터 형이면 1008이 될것이다.


즉 int형 기준으로 그앞에있는 메모리를 의미하게 된다.

-1은 반대로 뒤에있는 메모리이다.


#include <iostream>
#include <ctime>
using namespace std;

int main()
{
  int arr[3] = {1,2,3};
  int* x_ptr;
  x_ptr = &arr[0];  // 1이 위치한 메모리 주소값
  x_ptr++;      // 이제 다음 2가 위치한 메모리 주소값
  
  cout << *x_ptr << endl;
  return 0;
}


앞서서 배열은 메모리에 일렬로 저장된다고 했다

따라서 해당 결과는 2가 된다.


참고로 *와 /는 불가능하다

불가능은 둘째치고 할필요도 없다 메모리값을 곱해서 가르키는 메모리가 어딘줄알고 사용할것인가.




4. 더블 포인터


포인터도 변수이기때문에 어느 주소값에 저장이 되게 되어있다.

따라서 포인터의 주소를 가르키는 다른 포인터가 있을수 있는데

이것이 포인터의 포인터, 더블포인터이다.


#include <iostream>
#include <ctime>
using namespace std;

int main()
{
  int x = 10;
  int* x_ptr = &x;
  int** x_ptr_ptr = &x_ptr;

  cout << x << endl;
  cout << *x_ptr << endl;
  cout << **x_ptr_ptr << endl;
  return 0;
}


선언은 포인터의 포인터이기때문에 **을 2개 붙였다


사용도 *x_ptr_ptr을 하면 x_ptr의 값인 &x 일것이고

**x_ptr_ptr은 x_ptr이 가르키고있는 값인 x가 될것이다.



이것으로 포인터와 관련한 문법을 다 배웠다.

강의를 보다보면


아니 주소값을 저장해서 대체 어따쓰는건데? 생각이 들텐데

나중가면 다~쓰게 되어 있다.


실습

1. 포인터변수 하나와 변수 2개를 선언하고 포인터를 통해 값을 수정하라
2. int형 변수(4바이트) 하나를 선언한 뒤 1바이트당 각각 R,G,B,A (0~ 255)값을 저장 할 수 있도록 해보라





다음 강의는 배열과 포인터의 상관관계와 call by pointer 입니다.



728x90