💻 개인공부 💻/C | C++

[C++] 포인터 변수 (feat. * / & / **)

공대생 배기웅 2020. 6. 17. 18:51
반응형

 

 

포인터 변수란 무엇인가?

 

포인터변수란 data가 저장되어있는 메모리의 시작주소를 값으로 갖는 변수이다.

 

<typeName *PointerVariableName> 와 같은 형식으로 선언한다. 

 

주소를 얻어오기 위해서는 '&' 연산자를 변수 앞에 붙인다. 

 

▶ 주소가 주어졌을 때, 그 주소가 가리키는 곳의 값을 얻어오기 위해서는 *연산자를 사용한다.

 

 

#include<iostream>
using namespace std;

void main() {
	int x = 100;
	int *xp = &x; // 포인터 변수 xp에 x가 저장되어있는 메모리의 시작 주소값을 저장합니다.

	cout << "xp는 x의 주소값입니다.:" << xp << endl; 
    //xp는 주소값이므로 맨 처음의 주소값 출력
	
    
    cout << "&x는 x의 주소값입니다.:" << &x << endl; 
    //&x는 x의 주소를 나타내므로 맨 처음의 주소값 출력
	
    
    cout << "xp가 가르키는 값입니다 : " << *xp << endl; 
    //*xp는 x를 나태내므로 x의 값이 출력
}

 

 

포인터변수로 두 변수의 값을 변환하는 예제

 

#include<iostream>
using namespace std;

void swap(int a, int b) {
	int t;
	int* ap = &a;
//a의 주솟값을 &을 이용하여 불러옴
	int* bp = &b;
//b의 주솟값을 &을 이용하여 불러옴
	t = *ap;
//t라는 새로운 변수를 만들어 문자를 저장할 하나의 저장소 생성
	*ap = *bp;
	*bp = t;
	cout << "a:"<< a <<","<<"b:"<< b << endl;
}

void main() {
	cout << "변환할 두 수를 입력하세요" << endl;
	int a, b;
	cin >> a >> b;
	swap(a, b);
}

 

 

배열에서의 포인터

 

▶ 배열의 포인터변수를 알아보자

아래와 같이 변수를 정의했다고 가정하고 이 때의 메모리 구성은 다음과 같다.

 

int arr[4] = {1,3,5,7};
int* ip = arr;

 

 

▶ 배열의 시작 주소만 알면 배열의 모든 원소의 값을 알 수 있다.

 

▶ 배열을 사용할 때는 매개변수로 배열의 시작 주소만을 전달해주기 때문이다. 

#include<iostream>
using namespace std;

void main() {
	int a[] = { 1,2,3,4,5 };
	cout << "a=>" << a << "," << "a[0] =>" << &a[0] << endl;
//a의 주소값과 a[0]의 주소값을 출력한다.
//배열의 시작 주소를 전달하기 때문에 일치한다.
	cout << "a=>" << a+1 << "," << "a[0] =>" << &a[1] << endl;
	cout << "a=>" << a+2 << "," << "a[0] =>" << &a[2] << endl;
	cout << "a=>" << a+3 << "," << "a[0] =>" << &a[3] << endl;
	cout << "a=>" << a+4 << "," << "a[0] =>" << &a[4] << endl;

}

 

 

 

포인터 변수에 메모리 할당/ 해제

 

포인터 변수에 메모리를 할당하는 경우

다음과 같은 형식으로 할당한다.

typeName *pointerVariableName = new typeName;
int*ip = new int // ip라는 포인터 변수에 int 형의 메모리 할당

 

int형과 double형 메모리를 할당하는 예제를 보자

 

#include<iostream>
using namespace std;

int main() {
	int* ip = new int; //ip에 int형 메모리 할당
	*ip = 999; //ip 값에 999이라는 정수 값을 대입
	cout << "ip의 주소 : " << ip << endl;
	cout << "ip의 크기 : " << sizeof ip << endl;
	cout << "ip의 값 : " << *ip << endl;
	cout << "ip값의 크기 : " << sizeof * ip << endl;

	double* dp = new double; //dp에 double형 메모리 할당
	*dp = 777.77; //dp 값에 777.77이라는 유리수 값 대입
	cout << "dp의 주소 : " << dp << endl;
	cout << "dp의 크기 : " << sizeof dp << endl;
	cout << "dp의 값 : " << *dp << endl;
	cout << "dp값의 크기 : " << sizeof * dp << endl;
}

 

 

▶ 메모리 할당을 한 결과, ip는 int형이기 때문에 4byte 크기의 메모리가 할당되었고, dp는 double형이기 때문에 8byte 크기의 메모리가 할당되었음을 알 수 있다. 

 

▶ 다음은 포인터 변수에 할당된 메모리를 해제하는 경우이다.

다음과 같은 형식으로 할당한다.

delete pointerVariableName;
int *ip = new int;  //ip에 int형 메모리 할당
delete ip; // ip에 할당된 메모리 해제

 

▶ 할당된 int형 메모리를 해제하는 예제를 보자

 

#include<iostream>
using namespace std;

int main() {
	int* ip1 = new int;//ip1에 int형의 메모리 할당
	*ip1 = 999;
	cout << "ip1의 주소값 : " << ip1 << endl;
	cout << "ip1의 값" << *ip1 << endl;
	delete ip1; //ip1에 할당된 메모리를 해제

	int* ip2 = new int;//ip1에 int형의 메모리 할당
	*ip2 = 777;
	cout << "ip2의 주소값 : " << ip2 << endl;
	cout << "ip2의 값" << *ip2 << endl;
}

 

 

▶ ip1 값에 할당된 메모리를 해제하고, ip2 값에 다시 int형의 메모리를 할당한 결과, ip2의 포인터가 ip1의 자리에 할당되었음을 알 수 있다. 

 

 

 

동적 배열의 생성/ 해제

 

▶ 동적 배열은 다음과 같은 형식으로 생성한다.

typeName *pointerVariableName = new typeName [num of elements];
int *ip = new int [10]; // ip에 int형의 메모리 10개 할당

 

▶ 동적 배열 생성 예제

 

#include<iostream>
using namespace std;

int main() {
	int* ip = new int[3];
	ip[0] = 333;
	ip[1] = 777;
	ip[2] = 999;

	cout << "ip[0] = " << ip[0] << endl;
	cout << "ip[1] = " << ip[1] << endl;
	cout << "ip[2] = " << ip[2] << endl;

	ip++;
	cout << "ip[0] = " << ip[0] << endl;
	cout << "ip[1] = " << ip[1] << endl;
	cout << "ip[2] = " << ip[2] << endl; //None
}

 

 

▶ ip에 배열을 할당하고, ip++을 취한 결과, 값이 뒤쪽으로 밀려났음을 알 수 있다. 

 

 

▶ 동적 배열 해제 형식은 다음과 같다 .

 

delete [] pointerVariableName;
int *ip = new int[10]; // ip에 int형의 메모리 10개 할당
delete[] ip; // ip에 할당된 10개의 메모리를 해제

 

▶ 동적 배열 생성 예제

 

#include<iostream>
using namespace std;

int main() {
	int* ip = new int[3];
	ip[0] = 333;
	ip[1] = 777;
	ip[2] = 999;

	cout << "ip[0] = " << ip[0] << endl;
	cout << "ip[1] = " << ip[1] << endl;
	cout << "ip[2] = " << ip[2] << endl;

	ip++;
	cout << "ip[0] = " << ip[0] << endl;
	cout << "ip[1] = " << ip[1] << endl;
	cout << "ip[2] = " << ip[2] << endl; //None

	delete[]ip; //ip에 할당된 메모리 해제
	cout << "ip[0] = " << ip[0]; //error
}

 

 

▶ delete를 통해 해제된 ip 배열을 출력한 결과, 메모리가 없기 때문에 에러가 발생했음을 알 수 있다.

 

다중 포인터

▶ 포인터의 포인터, 즉 포인터 변수의 주소 값을 가지는 포인터 변수라고 보면 된다.

▶ 이를 다중포인터라고도 하는데, *를 여러번 이용하여 다중 포인터 변수를 선언한다.

 

#include<iostream>
using namespace std;

void main() {
	int x = 100;
	int* xp = &x;
	int** xpp = &xp;

	cout << "x의 주소값은 xp입니다." << "xp => " << xp << endl;;
	cout << "xp의 주소값은 xpp입니다" << "xpp=>" << xpp << endl;

}

 

객체 포인터

▶ C언어의 포인터와 동일하다

▶ 위에서 언급했던 것처럼, 객체의 주소 값을 가지는 변수라고 생각하면 된다.

▶ 객체 배열을 선언할 때는 기본 타입 배열을 선언하는 형식과 동일하다.

▶ 객체 배열 선언은 객체 배열을 위한 공간을 생성하여 주고, 배열의 각 원소 객체마다 생성자를 실행하여 준다. 

=> Circle이라는 클래스를 생성하고, Circle의 객체 배열 이름을 c라고 선언했을 때, c[0]의 생성자, c[1]의 생성자, 그리고 c[2]의 생성자를 각각 실행하여 준다.

▶ 매개변수가 있는 생성자는 호출할 수 없다.

▶ 배열의 각 객체마다 소멸자를 호출하여 배열을 소멸하는데 이때는 생성의 반대순으로 소멸한다.

=> c[2]의 소멸자, c[1]의 소멸자, c[0]의 소멸자

 

문제를 통한 정리(main메소드로 클래스 맞추기)

1. 객체 포인터 선언 및 활용 예제

#include<iostream>
using namespace std;

class Circle {



	//채워보시오


};


int main() {
	Circle donut;
	Circle pizza;

	cout << donut.getArea() << endl;
	
	Circle* p;
	p = &donut;
	cout << p->getArea() << endl;
	cout << (*p).getArea() << endl;

	p = &pizza;
	cout << p->getArea() << endl;
	cout << (*p).getArea() << endl;
}

2. 클래스의 배열 선언 및 활용

#include<iostream>
using namespace std;

class Circle {
	int radius;
public:
	Circle() { radius = 1;}
	Circle(int r) {
		radius = r;
	}
	void setRadius(int r) {
		radius = r;
	}
	double getArea() {
		return 3.14 * radius * radius;
	}
};

void main() {
	Circle circleArray[3];


	//채워보시오


}

3. Circle클래스의 2차원 배열 선언 및 활용

#include<iostream>
using namespace std;

class Circle {
	

	//채워보시오

};

void main() {
	Circle circles[2][3];


	//채워보시오


}

 

728x90
반응형

'💻 개인공부 💻 > C | C++' 카테고리의 다른 글

[C++] 프랜드 함수  (0) 2020.06.19
[C++] 생성자와 소멸자  (0) 2020.06.18
[C++] 조건문 (feat. if 문과 switch 문)  (0) 2020.06.17
[C++] 포맷 플래그  (0) 2020.06.12
[C++] vector Container  (0) 2020.06.10