블로그 이미지
초딩입맛제주아재
하고 싶은 것만 하며 살고 싶다

calendar

1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30
2007. 2. 22. 16:53 Programing
출처: http://blog.naver.com/tb/hunhak/4274412




--------------------------------------------------------------------------  
  포인터에 관한 주저리 ....
--------------------------------------------------------------------------


1. 도대체 포인터를 왜 쓰는데..??? 힘들게 시리...


보통 C / c++ 에서는 포인터라는 개념을 많이 쓰고 있다.

그렇담 포인터란 뭘까?

나는  말하길 특정 주소에 들어 있는 데이타 값이라고 생각한다.

사용법은 이렇다.

먼저, 포인터 변수를 선언하고.

int *p ;

특정 주소를 대입한다.

p = &a;

이렇게 하면 *p 는 a 와 같다.

편의상 int *p = &a;  이렇게 표현하기도 한다.

그럼 왜! 포인터를 사용할까?  난 항상 세상 모든 현상에 대해서 왜!!! 라는 질문을

하곤 한다.

참고로 내 대학 평점은 c+ 이다.

'이 자식 공부 드럽게 안했구나.' 라고 생각하는 사람도 분명 있을 것이다.

하지만, 나는 대학시절 내가 "왜!!!" 공부를 해야 되는지 몰랐다. 그래서 안했다.

암튼 헛소리 그만하고 왜!! 포인터를 사용해야 되는지 알아보자..

#include<stdio.h>

void swap(int, int);

int main()
{
       int a = 10, b = 20;

       swap(a , b);

       printf("\n a , b = %d, %d \n", a , b );
}

void swap(int a, int b)
{
       int t;

       t = a;
       a = b;
       b = t;
}

다음을 컴파일하고 실행시켜 보니까, a 와 b 값이 서로 바뀌지 않고 a = 10, b = 20

이 출력되었다. 그이유는 main 함수에서 선언된 a ,b 값과 swap 함수에서 선언된 a, b 의 값은

데이타는 같지만 서로 다른 메모리 영역을 차지하고 있기 때문에 한마디로 엉뚱한 값을 변경한

결과가 되는 것이다.

물론 글로벌 변수를 사용하면 되겠지만, 글로벌 변수를 남용하면 프로그램상의 심각한 버그를 만들어

낼수도 있다.

그러므로 swap 함수의 인자값으로 해당 변수의 값이 아닌 주소를 넘겨 보면, 같은 주소에 있는 값을

변경 할수가 있을 것이다.

#include<stdio.h>

void swap(int *, int *);

int main()
{
       int a = 10, b = 20;

       swap(&a , &b);

       printf("\n a , b = %d, %d \n", a , b );
}

void swap(int *a, int *b)
{
       int t;

       t = *a;
       *a = *b;
       *b = t;
}

위의 소스를 컴파일 해보면 만족할 만한 결과를 얻을 수 있을 것이다.


2. 그럼 함수 포인터는 뭐냐 ???


함수 포인터란, 일반 포인터 변수와 마찬가지로 포인터 변수가 함수의 주소 부분을 가르키는 것을 말하고

함수를 다른 함수의 매개 변수로 사용할때 이용된다.

여기까진 설명이 됐지만 그렇담, 왜 !!!!!!!! 함수 포인터를 사용해야 되는 가에 대해서는 언급되어 있지

않다. 

음 ~ .... 함수가  변수처럼 다름 함수의 인자로 사용된다면, 변수는 말그대로 변하는 수이므로 함수도

변수처럼 변하는 함수를 매개변수로 사용하는 경우에 이용하면 되겠군....

예제를 준비했다.

bubble 정렬 함수가 있다고 하자, 이 함수는 문자열도 정렬해주고 숫자도 정렬해준다고 치자.

그럼 문자를 정렬해주는 함수 bubble_char(), 숫자를 정렬해 주는 함수 bubble_num() 두개를 만들어야

되는군... 약간 귀찮군. 그럼 만약에 정수 정렬 함수, 실수 정렬 함수 등 더 많은 함수들이 필요하다면,

bubble_int();
bubble_float();
...
..
.

이런식의 함수가 많이 필요할 것이다.

여기서 함수 포인터를 사용해 보도록 하자. bubble 함수 하나만 만들고, 각각의 문자열의 크기 비교

숫자 크기 비교 하는 함수를 만들어서 0 또는 1 만 반환하게 한다음 정렬은 bubble 함수에게 시키자.

그럼 훨씬 소스가 간결해 질것이다. 

아래 소스는 발췌한 것임을 알림....


#include <stdio.h>
#include <string.h>

#define MAX_BUF 256

long arr[10] = { 3,6,1,2,3,8,4,1,7,2};
char arr2[5][20] = {  "Mickey Mouse",
                     "Donald Duck",
                     "Minnie Mouse",
                     "Goofy",
                     "Ted Jensen" };

void bubble(void *p, int width, int N,
           int(*fptr)(const void *, const void *));
int compare_string(const void *m, const void *n);
int compare_long(const void *m, const void *n);

int main(void)
{
   int i;
   puts("\nBefore Sorting:\n");

   for (i = 0; i < 10; i++)               /* show the long ints */
   {
       printf("%ld ",arr[i]);
   }
   puts("\n");

   for (i = 0; i < 5; i++)                  /* show the strings */
   {
       printf("%s\n", arr2[i]);
   }
   bubble(arr, 4, 10, compare_long);          /* sort the longs */
   bubble(arr2, 20, 5, compare_string);     /* sort the strings */
   puts("\n\nAfter Sorting:\n");

   for (i = 0; i < 10; i++)             /* show the sorted longs */
   {
       printf("%d ",arr[i]);
   }
   puts("\n");

   for (i = 0; i < 5; i++)            /* show the sorted strings */
   {
       printf("%s\n", arr2[i]);
   }
   return 0;
}

void bubble(void *p, int width, int N,
           int(*fptr)(const void *, const void *))
{
   int i, j, k;
   unsigned char buf[MAX_BUF];
   unsigned char *bp = p;

   for (i = N-1; i >= 0; i--)
   {
       for (j = 1; j <= i; j++)
       {
           k = fptr((void *)(bp + width*(j-1)), (void *)(bp +
j*width));
           if (k > 0)
           {
               memcpy(buf, bp + width*(j-1), width);
               memcpy(bp + width*(j-1), bp + j*width , width);
               memcpy(bp + j*width, buf, width);
           }
       }
   }
}

int compare_string(const void *m, const void *n)
{
   char *m1 = (char *)m;
   char *n1 = (char *)n;
   return (strcmp(m1,n1));
}

int compare_long(const void *m, const void *n)
{
   long *m1, *n1;
   m1 = (long *)m;
   n1 = (long *)n;
   return (*m1 > *n1);
}



3. 그럼 이차원 포인터는 뭐냐 ???


아래와 같은 배열이 있다고 치자...

1, 2, 3, 4
5, 6, 7, 8

a[0][0] = 1;
a[0][1] = 2;
a[0][2] = 3;
a[0][3] = 4;
a[1][0] = 5;
a[1][1] = 6;
a[1][2] = 7;
a[1][3] = 8;

이것을 하나의 배열로 저장하면 위와 같은 이차원 배열이 된다.

그럼 포인터로 위 배열 요소들을 접근해 보자.

a 의 주소는 &a 이고 니깐. *a 라고 하면 뭐가 나올까?

그럼 a 의 주소값인 a[0] 의 값으로써 이상한 메모리 번지가 나올 것이다.

1 항목을 가져 올려면 어떻게 해야 되지?

1 은 a[0][0] 값이다. 이것은 주소 a[0] 에 있는 값이된다.

*a[0] 는 주소 a[0] 에 있는 값이므로 1 이되고, **a 라고 표시할 수도 있다.

그리고 만약 5 에 접근하기 위해서는 *(a+1)[0] , **(a+1) 이라고 쓰면 된다.

posted by 초딩입맛제주아재