프로그래밍 언어/C & C++ 정리

포인터

뽀또치즈맛 2023. 1. 4. 21:39

포인터는 ' * ' 연산자를 쓴다

' * ' 연산자는 간접 연산자라고도 불리며,

역참조 연산자라고도 불린다.

 

포인터는 데이터가 저장된 주소값을 가리킨다.

그리고 이 주소로 해당 주소의 값에 접근하여,

값을 변환하거나 동적할당을 할 때 쓴다.

 

<예     시>

int *pa;

예시에서 int는 주소를 구한 변수의 형태이고,

*는 포인터의 기호,

pa는 포인터의 이름이다.

 

포인터의 변수가 선언되면

일반 변수와 마찬가지로 메모리에 저장 공간이 할당되며,

그 이후에 변수명으로 사용 가능하다.

 

pa = &a;

 

만약 변수 a가 메모리 100번지부터 103번지까지 할당되었다면

주소 값이 100이고 pa에 저장된다.

 

그렇게 되면 pa는 변수 a가 메모리 어디에 할당되었는지

그 위치를 기억하고 있게 된다.

 

pa -> a

이러한 과정을 통해 포인터 pa는 변수 a를 가리킬 수 있다.

 

주소와 포인터의 차이

 

주소는 변수에 할당된 메모리 저장 공간의 시작 주소 값의 자체이며,

포인터는 그 값을 저장하는 또 다른 메모리 공간이다.

 

따라서 특정 변수의 주소 값은 바뀌지 않지만

포인터는 다른 주소를 대입하여

그 값을 바꿀수 있다.

 

이때 변수 a의 주소는 100이라 가정하면 프로그램 실행 중에서 그 값은 바뀌지 않는다.

그러나 포인터 pa는 만약 변수 b를 대입하느냐 a를 대입하느냐에 따라

 

가리키는 변수가 바뀐다.

 

즉 이러한 말은

주소는 '상수'이고, 포인터는 '변수'라는 뜻이다.

 

따라서 두 포인터가 같은 주소를 저장하는 일, 

즉 하나의 변수를 동시에 가리키는 일도 가능하다.

 

주소와 포인터의 크기

 

포인터도 저장 공간이므로 그 크기가 있다.

포인터의 크기는 저장할 주소의 크기에 따라 결정되는데

크기가 클수록 더 넓은 범위의 메모리를 사용할 수 있다.

 

포인터의 x86에서는 4바이트이고 x64에서는 8바이트가 된다.

 

const와 포인터의 관계

 

const란? 제한자

const는 변수를 상수 취급할 때 쓴다.

변수의 초기값을 변경할 수 없는 변수로 만든다.

값의 변동을 제한을 하겠다.

const의 위치에 따라 값을 바꿀 수 있게 하느냐,

주소를 바꿀 수 있게 하느냐이다. 

 

const를 왜 써야하는가?

사용자에게 안전한 프로그래밍을 제공하기 위해 사용하는 것이다.

const 제한을 통해 다른 사용자 혹은 몇일 후의 자신이 안전한 접근만 허용하도록 제한 가능하다.

추후에 포인터 혹은 참조자를 주로 사용하게 되면 해당 전달 인자에 대한 변동을 막아야 한다.

 

 

const int* a 와 int* const a 차이

 

포인터 변수의 상수화는 두 가지 개념이다.

이는 const가 붙는 위치에 따라 달라진다.

 

1. 내가 가르키고 있는 대상의 원본을 상수화 할지,

2. 내가 상수화되어 더 이상 다른 대상을 가르키지 못할지인지.

 

< 예   제 1 >

int a = 10

const int * pConstint = &a;

*pConstint = 100;     

 

위 예제는 오류가 난다.

이는 포인터가 가리키는 주소를 상수화 한 것이기 때문이다.

 

 

< 예   제 2 >

int b = 0;

int * const pIntConst = &a;

 

포인터 변수 자체가 상수화 된 것으로

내가 가르키는 a의 내용물은 바꿀 수 있으나

다른 주소를 받을 수는 없다.

 

 

자, 그럼 이제

이 둘의 특징을 가지는 예제를 살펴보자

 

< 예   제 3 >

const int * const pConstIntConst = &a; 

 

이는 변수의 값, 변수의 주소 모두 불변으로 선언한 것이다.

물론 const로 설정한 값을 

어거지로 다른 포인터로 건들일 수는 있지만,

프로그래밍상 이 부분의 이 값은 건들이지 말자고 

서로 간의 약속을 한 것이기 때문에

그런 코딩은 지양하도록 하자.

 

const 가 어느 곳을 수식하느냐에 따라 다르다.

둘다 *연산자와 같이 쓰이고 있지만

 

1번 예제를 쉽게 풀어보면

const가 ( int * pConstint = &a ) 를 수식하는 것이다.

그렇다면 int는 정수를 뜻하는 자료형이니 잠시 코드를 편하게 읽기 위해

편의상 빼겠다.

 

그럼 const 가 수식하는 것은 *pConstint = &a 인 것인데

이겨서 더 직관적으로 간단화 하면,

*pConstint 를 간단하게 a를 가르키는 포인터 이니,

*cpa라고 칭하겠다.

const 가 수식하는 것은 *cpa = &a 가 되는 것이다.

 

뭔가 느낌이 오지 않는가?

역참조 연산자를 달고 다니는 포인터가 주소값을 가지고 있으면

출력은 주소가 가지고 있는 값을 배출한다.

 

이 값을 상수화 하겠다는 의미이다. 

 

 

그럼 이제 예제 2번을 살펴보겠다.

int * const pConstint = &a 이다.

먼저 편의상 int 를 빼보겠다.

이번에는 포인터가 선행이다.

그럼 포인터가 실행할 값은

고정된 pConstint = &a이 된다.

 

그럼 이해를 돕기 위해

선행자는 포인터이고

그런 포인터는 값을 구해와야 하는데

제한자가 바로 앞에 있으니,

 

제한자를 읽고 어떤 값이 제한되는 가? 를

읽어보니 변수 pConstint 라는 것이다.

그 변수 pConstint는 이름이고 실질적 알맹이는 a의 주소값이다.

 

때문에 선행자가 무엇이냐에 따라

실행 결과가 달라지거나

 

예제 3번처럼 두 가지를 다 실행 할 수 있는 것이다.

 

 

 

 

 

 

 

배열과 포인터의 관계

 

 

+ pointer 초기화

 

pint = nullptr;

하면 포인터는 어떠한 곳도 가리키지 않는다.

 

 

 

+ 변수 c++개념

 

lvalue

 

표현식 이후에도 사라지지 않는 값. 이름을 지니는 변수.

 

rvalue

 

표현식 이후에는 사라지는 값. 임시 변수.

'프로그래밍 언어 > C & C++ 정리' 카테고리의 다른 글

동적 할당 함수  (0) 2023.01.07
c++ 함수의 특질  (0) 2023.01.07
함수  (0) 2023.01.06
버블 소트 Bubble Sort  (0) 2023.01.04
배열  (0) 2023.01.04