1. 포인터 배열(Array of Pointer)이란 ? 

   = 요소가 포인터로 이루어진 배열 


ex) 크기 5인 정수형 포인터 배열 


 int *arpi[5];     // 정수형 포인터 5개가 모여 이루어진 배열



#include<stdio.h>

#include<stdlib.h>

 

void main(void)

{

     char *arps[]={"고양이","개","오랑우탄","돼지","지렁이"};

     int i;

 

     for (i=0;i<5;i++) {

          printf("%s\n",arps[i]);

     }

} 

 



  각 문자열들은 메모리상에 흩어져서 존재

  위치에 상관없이 이 문자열들에 대한 반복처리 가능

  이렇게 만들어진 문자열 배열을 [ Ragged 배열 ] 이라 한다.

  (장점 : 개별 문자열의 길이가 달라도 낭비되는 메모리가 없다)




2. 포인터 배열의 활용


 3개 학급의 성적 처리를 할 수 있는 예제


#include<stdio.h>

#include<stdlib.h>

 

void main(void)

{

     int *ar[3];

     int num[3];

     int i;

 

     for (i=0;i<3;i++) {

          printf("%d반의 학생수를 입력하세요 : ",i+1);

          scanf("%d",&num[i]);

          ar[i]=(int *)malloc(num[i]*sizeof(int));

     }

 

     // 여기서 성적을 처리한다.

 

     for (i=0;i<3;i++) {

          free(ar[i]);

     }

} 

 

   1. 각 학급의 학생수를 입력받아 num배열에 저장

   2. 입력된 수 만큼 메모리 동적할당

   3. ar배열에 차례로 그 번지를 저장

   4. ar배열이 가리키는 포인터들은 각 학급 학생들의 성적을 저장할 수 있는 

      배열이 됨 .

   5. 성적 처리가 끝난 후 free함수로 해제


   이렇게 만들어진 ar배열은 2차 정수형 배열같이 사용 가능


   ex) ar[0][1]  -> 0번째 학급의 1번째 학생의 성적



3. 포인터와 배열

   

   int ar[n];      -> ar[n]은 n개의 정수형 변수를 모아놓은 배열이다. 여기서 n은 변수가 아니라 상수.  sizeof(ar) = 20  

int *pi         ->  pi는 정수형 변수 하나의 위치를 가리킬 수 있는 포인터



But! 동적 메모리 할당으로 pi로도 정수형 배열을 가리킬 수 있다


pi=(int *)malloc(n*sizeof(int));


그림으로 도식화해보면


pi는 ar과 똑같은 자격을 가지며 정수형 배열처럼 행세할 수 있다. 

pi나 ar이나 둘 다 배열의 선두 번지를 가리키며 ar[2]로 2번째 요소를 읽을 수 있듯이 pi[2]로도 2번째 요소를 읽을 수 있다. 

    

그렇다면 다른점은?


① 포인터 = 변수  vs  배열 = 상수이다

   pi는 고유의 메모리를 차지하고 있고 언제든지 다른 대상을 가리킬 수 있지만 ar은 선언할 때 그 위치가 이미 고정되므로 다른 대상을 

   가리킬 수 없다. ar로는 오로지 배열의 선두 번지를 읽을 수 있을 뿐이며 이 선두 번지를 기준으로 하여 배열 요소를 읽는다.

② pi가 가리키는 배열의 크기는 동적으로 결정가능  vs   ar이 가리키는 배열의 크기는 선언할 때 정적으로 결정

   고정된 길이의 배열이 필요하면 int ar[n]; 선언문으로 배열을 생성하는 것이 편리하고 가변 길이의 배열이 필요하면 int *형의 포인터 변수를 

   선언한 후 malloc으로 할당해서 사용해야 한다. 포인터로 할당한 배열은 실행중에라도 realloc으로 크기를 재할당하여 변경할 수 있다.

③ 배열은 그 자체가 크기 때문에 함수의 인수로 전달할 수 없다  vs  포인터는 대상체가 무엇이든간에 4바이트의 크기밖에 차지하지 않으므로 함수로 전달할 수 있다

   그래서 배열을 함수로 전달할 때는 반드시 포인터를 사용해야 한다.

④ 배열로 요소를 읽는 것과 포인터로 대상체를 읽는 동작은 속도 차이가 있다

   배열의 첨자 연산은 매번 배열 선두에서부터 출발하지만 포인터는 대상체로 직접 이동해서 바로 읽으므로 액세스 속도가 빠르다. *pi는 pi가 가리키는 곳을 바로 읽지만 ar[n]은 *(ar+n)으로 일단 번지를 더한 후 읽어야 하므로 조금 느리다. 대단한 속도 차이는 아니지만 대규모의 반복적인 루프에서는 이 속도차도 결코 무시 못할 정도로 크다. 대략 포인터가 배열보다 두 배 정도 빠르다.




심화


I. int *api[5];    -> 위에서 살펴봤던 포인터 배열이다


 포인터배열의 각 요소들은 정수형 변수 or 동적 할당된 정수형 배열을 가리킬 수 있다


  II. int **papi;    -> 위와 같은 api같은 포인터 배열을 가리킬 수 있다.

 




출처 : www.soen.kr


'Engineering > Data Sturcture' 카테고리의 다른 글

포인터공부7 - 구조체  (0) 2016.03.19
포인터공부4 - 이중포인터  (0) 2016.03.16
포인터공부3 - 동적메모리 할당  (0) 2016.03.15
포인터공부 2  (0) 2016.03.15
포인터공부 1  (0) 2016.03.15

+ Recent posts