알음알음-IT/개발_기초_코딩_C

초급 C언어 공부 - 3.포인터(1)

구구닥스 2020. 2. 4. 14:20

오늘은 포인터에 대해서 간략하게 설명드리겠습니다.

간단하게 포인터란 메모리에 있는 데이터의 주소를 가지고 있는 변수입니다.

 

메모리 상에 있는 데이터들은 모두 주소를 가지고 있습니다. 마치 우리들이 사는 집의 주소와 같은 형식으로요

그런데 포인터는 데이터 값을 가지고 있는게 아니고 주소값을 가지고 있는 변수인겁니다.

굳이 왜 값이 아닌 주소를 가지고 있냐면 바로, 데이터의 복사를 피하고 복잡한 자료구조를 효율적으로 처리하며 메모리를 효율적으로 쓰기 위해서입니다.

즉 효율적이기 위해서 쓰는것입니다.

 

포인터를 보기 이전에 우리가 알고있는 변수는 모두 주소값을 가지고 있습니다.

우리가 변수를 선언하는 순간 그 변수는 주소를 부여받고 거기에 데이터값을 저장하는거지요

자료형을 보시다 싶이 자료형마다 데이터 크기가 다릅니다

int는 4바이트 char는 1바이트 float는 4바이트를 차지하지요 실제로 코드로 확인해보겠습니다

 

 ...

 8059144-8059147

 ...

8059159-8059160

... 

... 

8059168-8059171 

... 

... 

 ...

 

 12.3

 

 69

 

 

 10

 

 

 

 

이런 식으로 주소에 데이터 값이 부여되어 있는 것입니다. 

 

&는 주소 연산자라고 해서 변수의 이름을 받아 주소를 변환해주는 연산자입니다.

실제로 변수가 주소에 데이터를 가진다는 것을 봤으니 포인터로 어떻게 주소값을 가지는지 알아보겠습니다.

 

어떠한 포인터 pi로 변수 i값을 가리키면 그 포인터가 가지는 데이터는 바로 i의 주소값이 되는 겁니다.

위의 코드로 보자면 포인터 pi의 값은 8059198이 되는겁니다.

맞는지 확인해 볼까요?

어떠한 포인터 pi를 *pi = NULL 값으로 우선 초기화 선언을 해줍니다.

int *pi  해석해보면 정수를 가르키는 포인터 pi가 되는 셈입니다

NULL로 초기화한 이유는 쓰레기 값이 들어가지 않게 하기 위함입니다.

 

선언을하고 pi = &i로 가르키는 주소를 지정해줍니다. 변수 i의 주소를 가르킨다는 뜻이죠

그걸 확인해보기 위해서 i의 주소값과 pi의 값 그리고 *pi의 값을 나타내봤습니다.

그리고 포인터 pi또한 변수이기 때문에 주소를 가지고 있습니다.

 

 

 변수 I

 

 

 

 포인터 pi

 

 

 

 

 

 8714164~8714167

 

 

 

8714176~8714179 

 

 

 

 

 

 10

 

 

 

 8714164

 

 

 

이런식으로 주소와 값을 가지고 있는겁니다

여기서 *란 간접 참조 연산자라고 합니다 이 간접 참조 연산자는 포인터가 단순히 주소만 가지고 있는 것이 아니라 가리키는 주소의 값을 불러오는 역할을 

하기 때문에 중요합니다. *pi는 pi가 가지고 있는 i의 주소값에 있는 데이터 10을 불러오라는 뜻입니다.

이 * 간접 참조 연산자는 값을 읽어오는 것과 동시에 값을 변경할 수도 있습니다. i를 건드리지 않고 포인터로만 i의 값을 바꿀 수 있다는 뜻입니다.

 

코드를 보면 *pi = 25로 *pi값을 바꿨는데 이 코드는 포인터 pi가 가리키는 주소의 데이터를 25로 바꾼다라는 뜻입니다.

보시는 것처럼 i의 값이 10에서 25로 변했습니다. 또한 14행 *&pi의 값이 pi의 값과 동일하게 변수 i의 주소를 가리키고 있습니다.

이 *&pi를 해석해보면 pi의 주소값에 담긴 데이터 값이기 때문에 그냥 pi의 데이터 값이 나오는 겁니다. 

마치 서로 상쇄되듯이 생각하시면 편리합니다. 무조건 상쇄되는것이 아니란 것도 알아두셔야 합니다.

 

포인터를 사용하실 때 주의할 점 몇가지가 있습니다. 포인터는 단순히 주소값만을 가지는데 왜 자료형 타입을 쓰냐고 물어보면

그 이유는 포인터에 의해 참조되는 객체가 얼마큼인지 무엇이 어떤식으로 결정되는지는 포인터 타입에 따라 결정되기 때문에

서로 다른 타입이라면 오류가 발생합니다 따라서 포인터의 타입과 참조되는 변수의 타입은 같아야 합니다.

그리고 위에서 처음 포인터를 사용할 때마다 NULL값으로 초기화 했는데, 이 NULL값은 stdio.h에서 0으로 결정되어 있습니다. 그러면

주소 0값을 가지게 되는데 주소 0을 액세스 하려고 하면 자동적으로 오류를 감지해서 해결할 수 있기 때문입니다.

주소 0값은 cpu에서 사용하는 영역이기 때문이죠 그러니 포인터를 사용하기 전에는 NULL값으로 초기화가 필요합니다.