Canvas of Bliss

C++ 포인터

2020. 10. 8. 00:16

#include <iostream>

using namespace std;

void Plus_One(int* _n);

void main()
{
 메모리 주소
 메모리 주소를 확인하기 위해서는 &(어드레스 연산자)를 사용한다.
& + 변수명 을 명시하면 해당 변수가 할당된 메모리의 시작 주소를 반환한다!

int iA = 10;

cout << "iA: " << iA << endl;
cout << "&iA: " << &iA << endl;


 포인터 선언
자료형과 변수명 사이에 *(에스크리터)를 추가해주면 된다.
/*
자료형  *  변수명
*/
int*  ptr1;
int * ptr2;
int  *ptr3;

int iA;
double dB;
long long llC;

int* ptr;
int iA;
double dB;
long long llC;


포인터의 초기화
쓰레기 값 초기화
int* ptr;

0으로 채워진 주소를 가진다.
이 주소는 0번지를 가리키는 것이 아니라 아무런 곳도 가리키고 있지 않다 라는 의미이다.
int* ptr1 = 0;
int* ptr2 = NULL;
int* ptr3 = nullptr;

cout << ptr1 << endl;
cout << ptr2 << endl;
cout << ptr3 << endl;


선언과 동시에 초기화
int iA = 10;
int* ptr = &iA;

cout << "iA: " << iA << endl; // iA의 값
cout << "&iA: " << &iA << endl; // iA의 주소
cout << "--------------------" << endl;
cout << "ptr: " << ptr << endl; // ptr의 값 == iA의 주소



포인터 초기화 시 주의 사항
##1. 쓰레기 값 초기화
-> 포인터 변수가 쓰레기 값을 가진다.
-> 포인터가 가지는 값은 주소이다.
-> 결국, 쓰레기 값이란 어디를 가킬지 모르는 주소이다.

만약, 쓰레기 값이 가리키는 곳이 윈도우를 구동하는데 중요한 메모리 공간이라면?
그 공간을 사용자가 임의로 값을 변경한다면?
운영체제에 심각한 문제가 발생한다!

단, 요즘의 운영체제는 특정 프로그램에서 할당되지 않는 메모리 접근의 시도가 있고
운영체제가 이를 감지한다면 해당 프로그램을 강제로 종료시켜버린다.


##2. nullptr 초기화
아무런 곳도 가리키고 있지 않다!
만약 접근하여 값을 확인 또는 수정한다면?
확인하고 수정할 값이 없다!!!
-> 오류가 발생한다!


주소를 통한 원본 데이터 접근
-> 간접 참조
* : 역참조 연산자
어느 상황에선 에스크리터, 어느 상황에선 역참조 연산자
 에스크리터 : 변수 선언 시 사용하면 에스크리터가 된다.
 역참조 연산자 : 변수 선언 후 변수명 앞에 붙이면 역참조 연산자가 된다.

 역참조 연산자를 읽는 방법은

 '해당 변수가 가지고 있는 주소로 찾아가 값을 확인해라!' 라고 읽으면 된다.
int iA = 10;
int* ptr = &iA; // 에스크리터

cout << "iA: " << iA << endl; // iA의 값
cout << "&iA: " << &iA << endl; // iA의 주소
cout << "--------------------" << endl;
cout << "ptr: " << ptr << endl; // ptr의 값 == iA의 주소
cout << "*ptr: " << *ptr << endl; // iA의 값


int iA = 1;

Plus_One(&iA);

cout << iA << endl;

}

// int* _n = &iA;
void Plus_One(int* _n)
{
++(*_n);
}

#include <iostream>

using namespace std;

void main()
{
 포인터의 크기
 어떠한 자료형이든 4bytes의 고정된 크기를 가진다.
 -> 32bits 개발환경에서 가용할 수 있는 메모리는 4기가이다.
 -> 포인터는 1byte당 하나의 주소가 할당되니 4기가를 byte단위로 환산하면
 -> 약 42억 9천만개가 나온다.
 -> 이는 0, 1, 2, 3, .... 약 42억9천을 각 저장하기 위해서는
 -> 4bytes의 공간만 있으면 충분히 저장할 수 있다!

-> 64bits 개발 환경에서는 동일한 계산 방식으로 8bytes의 크기가 나온다.
cout << sizeof(char*) << endl;
cout << sizeof(short*) << endl;
cout << sizeof(int*) << endl;
cout << sizeof(long*) << endl;
cout << sizeof(float*) << endl;
cout << sizeof(long long*) << endl;
cout << sizeof(double*) << endl;
cout << sizeof(long double*) << endl;


 int*, float* 는 서로 대입할 수 있을까?
-> 4bytes 공간이 필요하며, 주소를 저장한다!
int iA = 10;
int* ptr1 = &iA;

float* ptr2 = ptr1; // 불가능

불가능한 이유는 역참조 연산자를 붙여보면 된다.

ptr1이 가지고 있는 주소로 찾아가 값을 확인해라
값을 확인해라!
 ##1. 시작 주소부터 몇 바이트를 읽어야 하는가?
 ##2. 어떤 형식으로 읽어야 하는가?
 ptr1의 선언된 타입을 보면 int* 이다.
 이는, ptr1이 가지고 있는 주소로 찾아가
 해당 주소부터 타입의 크기(int)만큼의 공간을 타입 형태(정수형)으로 읽어라!
*ptr1;

 ptr2가 가지고 있는 주소로 찾아가
 해당 주소부터 타입의 크기(float)만큼의 공간을 타입 형태(실수형)으로 읽어라!
*ptr2;



 int*와 long* 는 대입이 가능할까?
 자료형의 크기는 운영체제 환경에 따라 다르게 적용된다.
 32bits환경에서는 int와 long의 크기가 같지만
 운영체제가 발전하여 업그레이드될 경우 int와 long의 크기가 같다고 보장할 수 없다!
int iA = 10;
int* ptr1 = &iA;

long* ptr2 = ptr1; // 불가능



 const와 포인터의 관계
 const는 바로 뒤에 있는 것을 상수화 시킨다!

 ##1. const가 에스크리터 앞에 올 경우
 const 뒤에 int*가 있다!
 -> 역참조를 통한 정수 값이 상수가 된다.
int iA = 10, iB = 20;

const int* ptr = &iA;

*ptr = 999; // 불가능
ptr = &iB; // 가능


 ##2. const가 에스크리터 뒤에 올 경우
 const 뒤에 ptr이 있다!
 -> ptr을 통해 확인할 수 있는 주소가 상수가 된다!
int iA = 10, iB = 20;

int* const ptr = &iA;

*ptr = 999; // 가능
ptr = &iB; // 불가능



}

 

#include <iostream>

using namespace std;

void main()
{
 이중 포인터
 포인터 또한 변수이다!
 -> 메모리에 등록이 된다!
 -> 포인터 또한 할당된 주소가 있다!

// 포인터 변수의 할당된 주소를 저장할 수 있는 것.

int iA = 10;
int* ptr = &iA;

cout << "iA: " << iA << endl;
cout << "&iA: " << &iA << endl;
cout << "---------------------------" << endl;
cout << "ptr: " << ptr << endl;
cout << "*ptr: " << *ptr << endl;
cout << "&ptr: " << &ptr << endl;
cout << "---------------------------" << endl;


// 포인터 변수의 주소를 저장하기 위해서는 2중 포인터가 필요하다!!
//int* ptr2 = &ptr; // 불가능
int** ptr2 = &ptr;

cout << "ptr2: " << ptr2 << endl; // ptr이 할당된 공간의 주소 값

// ptr2가 가지고 있는 주소로 찾아가 값을 확인한다!
cout << "*ptr2: " << *ptr2 << endl; // ptr이 가지고 있는 값 == iA의 주소
cout << "**ptr: " << **ptr2 << endl; // iA의 값


// ##1. 에스크리터와 역참조 연산자는 1:1의 비율로 작동한다!
// ##2. 포인터는 원본에 접근하는 방법으로 원본이 주소이다!







}

 

 

'개발 공부 > C++' 카테고리의 다른 글

C++ 배열, 2차원배열, 문자열배열, 3차원 배열  (0) 2020.10.08
C++ 자판기 프로그램 3  (0) 2020.10.08
c++ 자판기 프로그램 2  (0) 2020.10.07
C++ 함수, 포인터 개론  (0) 2020.10.07
C++ 삼항연산자, 함수  (0) 2020.10.07

이 글을 공유합시다

facebook twitter kakaoTalk kakaostory naver band