C++기초

220321(2) - 포인터(Pointer)

hyrule 2022. 3. 25. 16:38
#include <iostream>

int main()
{
	/*
	포인터 : 메모리 주소를 저장하는 변수 타입이다.
	int, float 등 모든 변수 타입은 포인터 타입을 선언할 수 있다.
	그래서 int변수의 주소는 int포인터 타입의 변수에 담을 수 있고
	float변수의 주소는 float 포인터 타입의 변수에 담을 수 있다.
	
	변수의 주소를 선언할때는 변수 앞에 & 을 붙여주면 해당 변수의 주소가 된다.

	32비트 타겟의 프로그램은 메모리 주소가 16진수 8자리가 나오게 되고
	64비트 타겟의 프로그램은 메모리 주소가 16진수 16자리가 나오게 된다.
	즉, 포인터 변수는 메모리 주소를 저장하는 변수이므로
	32비트 타겟에서는 4바이트가 되고,
	64비트 타겟에서는 8바이트가 된다.

	*포인터 사용시 주의할 점: 이미 지워진 메모리를 참조하게 될 경우 잘못 접근을 하면 문제가 발생한다.
		이렇게 지워진 메모리를 참조하는 포인터를 댕글링 포인터라고 한다.
	*포인터라는 건 C++의 최대 장점이자 단점이다.
		잘못 다뤘을 경우에 프로그램에 에러가 날 수 있기 때문

	


	main 함수가 동작이 되면서 메모리 내에 main 함수가 동작할 공간을 메모리에 할당한다
	main 함수가 끝나면 해당 메모리를 정리한다.
	변수의 숫자를 변경 = 메모리에 있는 값을 조작. 메모리 주소에 있는 해당 변수의 위치의 값을 변환
	*/

	int Number = 100;
	Number = 200;
	std::cout << &Number << std::endl;
	

	//포인터를 사용할 떄는 선언과 동시에 특정 주소를 주는 게 아니라면 nullptr로 초기화를 해 준다.
	//nullptr은 0이다.
	int* NumberAddr = nullptr;//초기화를 제대로 하지 않아서 실수하는 경우가 매우 많으므로 무조건 하도록 하자.

	//*포인터 변수가 다른 변수의 메모리 주소를 가지고 있는 것을 '참조한다'라고 표현한다.
	NumberAddr = &Number; //포인터 주소에 Number의 주소 등록

	//* 포인터 변수가 가지고 있는 메모리 주소가 있을 경우 해당 주소에 접근하는 것을 '역참조'라고 한다.
	//포인터 변수가 메모리 주소를 가지고 있을 경우 앞에 *을 붙이게 되면 해당 주소를 역으로 참조하게 되어서 해당 주소의 값을 가져오거나 값을 변경할 수 있게 된다.
	//역참조를 사용하는 이유: 다른 함수의 변수에 접근이 가능하다. ex)밖에 나왔는데 원격 제어(=포인터)로 집에 있는 컴퓨터에 접근하여 사용하거나 전원을 끌 수 있다.
	*NumberAddr = 999;
	

	
	std::cout << NumberAddr << std::endl;
	std::cout << "Number : " << Number << std::endl;
	std::cout << "Number Addr : " << &Number << std::endl;
	std::cout << "Number Addr Value : " << NumberAddr << std::endl;
	std::cout << "Number Addr : " << &NumberAddr << std::endl;

	//포인터도 마찬가지로 배열처럼 다중 포인터를 사용할 수 있지만, 잘 쓰지는 않는다.
	//많이 써봐야 이중 포인터

	//포인터를 사용하는 이유: 메모리의 '주소'를 알고있기 때문에 메모리에 무조건적인 접근이 가능하기 때문.

	int Array[100] = {};

	Array[1] = 30;//배열의 인덱스 접근을 보통 이렇게 한다.
	std::cout << "Array : " << Array << std::endl;
	//만약 인덱스 번호를 적지 않고 배열 변수를 출력하면 '메모리 주소'가 출력된다.
	std::cout << "Array[0] addr : " << &Array[0] << std::endl;
	//배열의 이름은 해당 배열의 첫번째 요소의 메모리 주소이다.
	//즉, 배열은 포인터 이다.
	
	//증명
	int* pArray = Array;
	pArray[1] = 999;
	std::cout << "pArray[1] : " << pArray[1] << std::endl;
	//Array[1]의 값이 정상적으로 변경된 것을 확인할 수 있다.


	//이차원 배열도 마찬가지이다. 하지만 접근이 매우 불편하다.
	int Array1[5][5] = {};
	//int* pArray1 = Array1; //에러 발생 --> 불편함


	////3월 22일날 나갈 내용
	//포인터는 배열과 아주 밀접한 관련이 있다.
	//char 배열에 문자열을 저장할때는 반드시 문자열의 가장 마지막 문자의 다음을 0(null 문자)로 주어야 한다.
	//그래야 문자열의 끝을 인식할 수 있다.
	char Text[32] = {};

	return 0;
}