본문 바로가기

프로그래밍/C언어

[C언어 with Java] 간단히 포인터에 대해서 알아봅시다.

 

C Prog. with Java


C언어를 다루고 있지만, 다른 프로그래밍 언어인 자바와 비교하면서 내용을 구성하고 합니다. 본 글은, 자바를 먼저 어느정도 알고 계시고, 저와 같이 C언어를  공부하고자 하는 분들에게 도움이 되길 바랍니다.

 

 자바에서는 포인터라는 개념이 없습니다. 포인터란 메모리에 직접적으로 접근을 해서, 메모리를 조작가능하게 하는 것인데, 포인터를 잘못 만지게 되면, 큰일(?) 납니다.

 

 메모리 공간에는 운영체제가 사용하는 메모리 공간이 있는데, 혹여 사용자가 이 공간을 침범하게 되면, 운영체제에 손상을 일으킬 수도 있게 됩니다. 이를 방지하기 위해서 자바에서는 포인터라는 개념을 개발 당시에 배제한것으로 알고 있습니다.

 

 때문에, 보다 주의깊은 사용법이 필요합니다.

 

 ** 물론 최근에 운영체제는 자신의 메모리 영역을 보호하기 때문에, 이를 시도할 시에는 에러 메시지를 띄우고 해당 프로그램을 종료시켜 버립니다.

 

 우선 포인터를 쓰는 데에는 두가지 연산자가 쓰입니다. 이 연산자를 일컬어, 포인터 연산자라고 부릅니다.

* - 메모리를 참조합니다.

& - 주소값을 반환합니다.

 

 백문이 불여일견. 어떻게 쓰이는지 알아봅시다.

 

 


 잘 보시면, 다음과 같이 해석 가능하겠습니다.

1번 : int 형 변수인 a 와 b는 각각 10과 20이라는 값을 가지고 있습니다.

2번 : 포인터 변수인 ptrA와 ptrB는 a와 b의 값을 담고 있는 메모리 공간의 주소를 담고 있습니다.

 

 1번에서는 우리가 보아왔던 그 형태와 동일합니다.

 2번에서는 포인터 변수임을 알리는 연산자 * 가 타입뒤에 명시되는데요. 이렇게 연산자를 적게 되면 앞에 명시해놓은 타입의 변수의 값을 가지고 있는 주소를 나타내는 포인터 변수를 선언하겠다라는 것입니다. 그리고 대입 연산자 뒤에 어떤 변수값 앞에 & 연산자를 써서, 실제 기술된 변수의 값을 가지고 있는 메모리 공간의 주소를 가리킵니다.

 

 ------------------ 여기서 잠시, 포인터 형(pointer type)에 대해서 잠시 짚고 넘어 갑시다.-----------------

데이터 타입에도 int 형, char형.. 등등 이 있듯이, 포인터에도 형(type)이 존재하며, 어떤 타입형 포인터라고 부릅니다.

int* : int 형 포인터

char* : char형 포인터

double* : double형 포인터

 

 다시 돌아와서,

 위의 소스를 출력해보면, 위와 같이 3143844, 3143832 라는 알수 없는 값을 출력해 놓은 것을 볼 수 있습니다.

그렇다면 이 포인터가 나타내는 실제값을 가리킬때는 어떻게 해야 할까요?

 

 대부분 눈치채셨겠지만, 어떤 실제 값의 주소를 담고 있는 포인터 변수 앞에 다시 * 를 쓰게 되면 실제 값을 위와 같이 확인 가능합니다.

 

 그렇다면, 이렇게 굳이 포인터를 쓰는 이유가 무엇일까요? 그냥 값 넣고 빼고 쓰면 되지 않을까요?

설명하기에 앞서서, 다음의 소스를 봅시다.

 

 

 

 

 색칠해 놓은 곳을 눈여겨 봅시다. 각 타입의 크기가 다른것은 다들 익히 아시고 계실겁니다.

눈치가 빠르신 분이라면, 빨간색 부분을 보고 이해를 하셨을텐데요, 타입은 달라도 포인터의 크기는 4바이트로 동일하다는 겁니다.

 

 결국, 포인터를 쓰게 되면, 가리키는 대상의 크기는 중요치 않게 됩니다. 4바이트로 고정되기 때문에, 좀더 가벼워 질수 있는 거죠. 그래서 함수의 인자로 받을 때, 효율이 좋습니다. 더 중요한 얘기는 추후에 하도록 하구요.

 

 제가 위에서 말한 부적절한 메모리 참조-OS 영역의 침해와 같은-를 하게 될 경우를 말씀해 드렸는데요. 가령 다음과 같은 상황을 설명할 수 있을 것 같습니다.

운영체제가 사용하는 메모리 공간을 1-20까지라고 합시다. 이때, 어떤 int형 포인터가 이 메모리 공간의 주소를 가리키고 있는데, 이때 이 포인터에 * 연산자를 사용해서 다음과 같이 값을 넣어주게 되면 운영체제에 영향을 미칠 수 있습니다.

 *ptr=21;

이렇게 되면 운영체제가 그 메모리 공간에 어떤 값을 사용하지 못하는 상황에서 사용자 임의로 바꿔버린 것입니다.

 

 이 상황은 보통 포인터를 초기화 하지 않은데에서 벌어집니다. 포인터를 초기화 하지 않고 쓰게 되면, 알 수 없는 쓰레기 값이 포인터에 저장되는데, 이 값을 주소값으로 해서 연산을 하는 경우에 벌어집니다.

** 이건 테스트 해볼려고 해도, 계속 초기화가 안되었다면서, 오류를 일으키기 때문에 예제를 보여드리지 못합니다.

 

 이를 방지하기 위해서는 NULL 포인터를 써야 합니다.

 여기서 NULL 포인터를 쓴다는 말은, 포인터를 초기화를 할때 NULL 또는 0 값으로 지정함을 의미합니다.

(NULL과 0은 동일한 의미이며, 그에 따라, 서로 대체가 가능합니다.)

 

다음과 같이 사용가능하겠습니다.

 

 

  실제로 포인터를 출력해보니 주소값이 둘다 0인것을 확인 할 수 있었고,

실제 값 같은 경우에는, 오류를 일으키며-화면에는 안보임-, 아예 실행이 안된것을 알 수 있습니다.

이로 미루어, 존재하지 않은 공간을 참조해서 값을 출력하려니, 오류를 일으킨 것으로 봐도 무방할 것 같군요.

 

 위와 같이, NULL 포인터를 쓴다면, 보다 안정적인 프로그래밍을 할 수 있을것 같군요.

 

 이상 글을 줄이구요. 다음 글에서는 배열과 포인터의 관계를 살짜쿵 들여다 볼까 합니다.