자료구조, 알고리즘

DS04 - 포인터

0verc10ck 2018. 5. 13. 03:38
반응형

포인터(Pointer)                  

  컴퓨터에서 사용하는 모든 변수는 메모리의 특정위치에 저장되는데 그 위치를 나타내는 메모리 주소를 포인터라고 한다.

포인터 변수(Pointer Variable)은 어떠한 변수의 메모리 주소(Memory Adress)를 저장하고 있는 변수이다.

그렇기 때문에 포인터 변수에 저장되는 값은 "0019FB26"과 같은 메모리 주소의 형태이다.

포인터 변수 P가 어떤 변수 A의 주소를 저장하고 있다는것은, 포인터 변수 P가 메모리상의 변수 A의 위치 즉, 주소값을 저장하고 있다는 뜻이다.

포인터 변수는 변수가 메모리를 포인트(가리키다)하고 있기 때문에 포인터 변수라는 이름을 가지게 되었다. 간단하게 "포인터" 라고 부르기도 한다.


  다음 그림은 포인터 변수의 형태를 나타낸것이다.



포인터 변수는 1021이라는 메모리의 주소값을 저장하고 있다.

메모리의 1021 번지에는 2라는 값이 저장되어 있고 포인터 변수를 사용함으로서 포인터 변수와 2라는 값을 가지고 있는 변수는 논리적으로 연결되어 있는 상태이다.


포인터의 선언 및 초기화                  

1. 포인터 변수의 선언

포인터는 다음과 같은 형식으로 선언한다.


int *p;
//자료형 *포인터변수이름;


- 1. 자료형 : 포인터 자체의 자료형이 아닌 포인터 변수에 저장될 주소에 있는 일반 변수의 자료형

- 2. 포인터이름 : 변수이름 설정시의 규칙을 따르지만 포인터변수라는 것을 표시하기 위해 변수이름 앞에 *를 사용


여기서 주의할 점은 포인터 변수를 선언할 때 포인터 변수의 자료형은 특별히 정해진 것이 아니라 포인터 변수에 저장될 주소

즉, 포인터가 가리킬 변수의 자료형을 따른다는 점이다.

또 포인터 변수는 특별히 정해진 자료형이 있는것이 아니기 때문에 일반 변수와 구분하기 위해 변수 이름 앞에 *를 사용한다.

또한 포인터 변수의 경우  메모리의 주소값을 저장하기 때문에 주소값의 크기인 4 byte를 변수의 크기로 가진다.


2. 포인터 변수의 초기화

  int, char 등의 자료형을 가진 변수를 선언하고 초기화 하지 않으면 변수에는 의미없는 값인 쓰레기값이 저장된다.

포인터 변수 또한 일반적인 변수들과 마찬가지로 선언 후 초기화 과정을  거치지 않으면 메모리상의 임의의 주소가 저장된다.

즉, 쓰레기값이 저장된다는 말이다. 따라서 포인터변수를 선언 할때에는 포인터 변수를 NULL로 초기화 해주는것이 좋다.

포인터 변수를 초기화 할 때 주의해야 할 점은 포인터 변수는 일반변수처럼 값을 저장하는 것이 아닌 메모리 주소를 저장한다는 점이다.


포인터 변수를 초기화 하는 방법은 다음과 같다.


- 1. 주소연산자를 사용하여 변수의 주소를 지정

int num; int *ptr = &i;

주소연산자(&)를 이용하여 변수의 메모리 주소를 직접 저장한다.


- 2. 동적 메모리를 할당하고 그 시작주소를 포인터 값으로 지정

char *ptr = (char*)mallloc(100);

동적 메모리를 할당하는 malloc()함수를 사용하여 문자형(char) 공간 100개를 할당하고, 그 시작주소를 포인터 변수 ptr에 저장한다.


- 3. 문자형 포인터에 문자열의 시작주소를 지정

char *ptr = "korea";

문자열 자료형은 일반 자료형과 달게 문자열 지정만으로 그 시작 주소를 전달할 수 있다.

"korea"문자열이 포인터 변수 ptr에 저장되는 것이 아니라 "korea"문자열이 저장된 위치의 시작 주소

즉, 'k'가 저장된 메모리의 주소가 포인터 변수 ptr에 저장된다.


- 4. 배열 이름을 이용하여 배열 시작 주소를 지정

char arr[10]; char *ptr = arr;

배열의 이름은 문자열과 마찬가지로 그 시작 주소를 전달할 수 있다.

포인터 변수 ptr은 문자형(char)요소를 100개 가진 배열 arr의 시작 주소를 저장한다.


-5. 배열의 첫번재 요소의 주소를 이용하여 배열 시작주소를 지정

char arr[10];
char *ptr = arr[0];

배열의 시작은 배열의 첫번째 요소, 즉 0번 인덱스의 배열 요소를 말한다.

그러므로 배열의 0번 인덱스 요소의 주소를 이용하여 배열의 시작 주소를 포인터 변수에 저장할 수 있다.

하지만 인덱스로 표시하는 배열의 각 요소는 그 자체로는 배열에 저장된 값을 가리키기 때문에 주소연산자(&)를 이용해야 한다.



포인터의 연산                                


C/C++에서 사용하는 포인터 변수관련 연산자는 주소연산자(Ampersand) '&'와 참조연산자(Asterisk) '*'가 있다.


1. 주소연산자(Ampersand) '&'

  주소연산자 '&'는 변수의 주소를 얻는데 사용된다.

즉, 변수 앞에 주소연산자를 사용하면 그 변수의 주소를 이용할 수 있다.

주의 할 점은 주소 연산자를 사용할 변수와 포인터 변수는 같은 자료형으로 선언되어 있어야 한다는 점이다.

int i = 10;
int *ptr = &i;
//포인터 = &변수;


2. 참조연산자(Asterisk) '*'

  다른 변수의 주소가 저장된 포인터에 참조연산자 '*'를 사용하면 저장된 주소영역(참조영역) 또는 저장된 주소 영역의 값(참조값)을 엑세스 할 수 있다.

아래의 1번 방법과 같이 지정 연산자의 좌변에 있는 포인터에 참조 연산자를 사용하면, 포인터가 가리키고 있는 주소 영역을 엑세스하여 포인터가 

가리키고 있는 주소에 해당하는 변수에 값을 저장할 수 있다.

또한 아래의 2번 방식과 같이 지정 연산자의 우변에 있는 포인터에 참조연산자를 사용하면, 포인터가 가리키는 주소영역이 가리키는 변수에 

엑세스하여 변수에 저장할 수 있다.

//1. *포인터 = 값;
int *ptr1 = 10;

//2. 변수 = *포인터;
int num = *ptr;


기타 포인터                                   

  

  포인터는 메모리의 주소값을 이용하는 만큼 다양한 연산을 쉽게 처리할 수 있게 해 준다.



1. 문자열 포인터


  포인터 변수를 이용하여 문자열의 시작 주소를 저장하면 문자열을 배열에 저장하는 것과 달리 배열의 크기를 정해주지 않아도 된다.

포인터 변수에 저장된 메모리 주소가 가리키는 값은 문자열의 첫글자에 해당하므로 반복문을 이용하여 문자열의 특정 부분을 수정할 수 있다.

혹은 다음에 나오는 포인터 배열을 이용하여 다중 문자열도 쉽게 저장할 수 있다.


  다차원 배열을 사용하여 다중 문자열을 저장하더라도 메모리에 실제 저장되는 형태는 연속적으로 저장된 형태이기 때문에 포인터를 이용한다면

배열의 각 요소에 엑세스하는 과정이 단순해지기도 한다.


2. 포인터 배열


  포인터 배열은 여러개의 포인터를 하나의 배열로 구성한 것으로 배열의 각 요소들은 포인터 변수를 저장하고있다.

포인터 배열을 선언하는 방법은 다음과 같다.


int *arr[4]
//자료형 *배열이름[배열의크기]

  

  이러한 방식으로 포인터 배열을 사용하면 포인터를 배열 처럼 이용할 수 있기 때문에 다중 문자열을 저장할 때 유용하다.

배열은 선언시 배열의 크기를 지정해주어야한다. 

만약 문자열의 길이 간의 차이가 크다면 배열의 크기가 문자열보다 지나치게 크거나 작은 문제점이

생길 수 있다. 

하지만 포인터 변수를 이용하여 문자열을 저장하면 문자열의 길이+1 만큼의 크기만큼의 공간을 할당하여 문자열을 저장하고, 배열은 포인터 변수만을 저장하기 때문에 메모리 낭비를 막을 수 있다.



3. 다중 포인터

  포인터 변수는  어떠한 변수의 주소를 저장하는 변수이다. 모든 변수는 메모리에 저장되기 때문에 저장된 주소를 가지고있다.

그렇기 때문에 포인터 변수 또한 저장된 메모리 공간의 주소가 있다.

이를 이용하여 포인터 변수의 주소를 또다른 포인터 변수에 저장하여 사용할 수 있다.

이를 이중 포인터라고 한다. 당연하게도 이중포인터를 넘어서 삼중, 사중으로도 포인터를 사용할 수 있다.


int **ptr;
//자료형 **포인터이름;(이중 포인터의 경우 삼중일경우 *를 하나 더사용)


이중 포인터의 경우 함수 내에서 함수 외부에서 선언된 포인터에 저장된 주소값을 변경하거나 사용하기 위해 사용한다.

반응형

'자료구조, 알고리즘' 카테고리의 다른 글

DS06 - 재귀함수  (0) 2018.05.15
DS05 - 구조체  (0) 2018.05.15
DS03 - 배열(Array)  (0) 2018.05.12
AL02 - 알고리즘의 성능 분석  (0) 2018.05.07
AL01 - 알고리즘의 이해  (0) 2018.05.07