1619, 1/81 회원가입  로그인  
   wolverine
   [자작] C 강좌 [5] - Pointer

http://www.hackerschool.org/HS_Boards/zboard.php?AllArticle=true&no=2038 [복사]



이번 장에서는 pointer에 대해서 알아보도록 하겠습니다.

pointer는 memory address를 통한 변수 access(read/write)를 위해서 필요한 개념입니다.
C에서 아래와 같이 변수를 선언할 수 있습니다.

int a;
unsigned short b;
char c;

여기에서 int, unsigned short, char 와 같은 것을 type keyword 라고 합니다.
이러한 type keyword는 compiler의해서 인식이 됩니다.
a,b,c 와 같은 것들을 variable instance라고 합니다.

즉, int type으로 'a'라는 instance를 만들어서 이용을 하겠다라는 뜻이며,
compiler/linker는 'a'라는 변수를 특정 memory address에 mapping을 시켜서
실질적으로 processor는 memory address를 기반으로 access(read/write)를 수행합니다.

[Note]
C는 high level language이기 때문에,
코딩을 하는 개발자는 a라는 변수의 memory 번지가 어디인지 신경쓸 필요없이,
단순히 a 라는 변수의 이름으로 편하게 access를 할 수 있습니다.
하지만, 특별한 경우에는 a가 할당되는 memory address를 직접 지정해 줄 수도 있습니다.

실제 compile된 instruction(machine code)은
a,b와 같은 논리적인 이름으로 변수를 access하는 것이 아니라,
항상 compiler/linker에 의해서 mapping된 address를 기반으로 해당 변수를 access하게 됩니다.

int a;
a = 1;
printf("%x", a);

라는 코드는 화면에 a에 저장되어 있는 '1' 이라는 값을 출력하게 됩니다.

반면에,

printf("%x", &a);

라는 코드는 화면에 1000f000(예) 과 같은 a라는 변수가 mapping된 address를 출력하게 됩니다.

여기서 변수이름 앞에 붙은 '&'라는 기호는 address를 나타냅니다.
즉, '&a'는 변수 a의 address를 말합니다.

자 그럼, pointer는 주로 언제 이용을 할까요?

void func1(int a, int b, int c)
{
    c = a+b;
    return;
}

라는 함수가 있는데,
이 함수가 a+b의 값을 c에 저장하는 기능을 하도록 해야한다고 가정을 해보죠.

int e;
int f;
int g;

e = 10;
f = 20;
g = 0;

func1(e,f,g);

라고 하면, g에 원하는 결과를 집어 넣을 수 있을까요?

답은 아니오 입니다.

이러한 경우를 call by value 라고 합니다.
함수가 value, 즉 값을 매개변수로 해서 호출 되었다는 뜻입니다.
func1(int a, int b, int c) 내부에서 a,b,c는
매개변수인 동시에 local 변수 입니다.
즉, a,b,c는 func1의 life time과 생사를 같이하고,
func1이 반환되는 시점에서 그 생명을 다하고 없어지게 됩니다.

func1(e,f,g) 라고 호출을 하면,
func1(10,20,0) 이라고 호출한 것과 동일한 의미 입니다.
func1의 시작과 함께,
매개변수 a=10, b=20, c=0으로 초기화 되어서,
func1 내부에서 이용이 되는 것 입니다.

따라서, c = a+b는 g에 값을 저장하지 못하고,
단순히 0값을 가지고 있는 c에 30이라는 결과를 저장하고,
함수의 반환과 함께, c는 소멸되어 버리게 됩니다.

그렇다면, g에 func1의 결과를 저장하려면 어떻게 해야 할까요?

이러한 경우 pointer가 이용이 됩니다.

int *c 라고 선언을 하면,
변수 c 를 int 변수의 address를 저장하는 변수로 사용하겠다는 의미 입니다.
여기서 '*' 기호는 pointer를 의미합니다.

Address는 말 그대로 물리적인 address를 의미하며,
Pointer는 이러한 address를 저장하는 변수를 의미 합니다.

int *c;
int d = 10;

c = &d;

라고 하면 'pointer 변수 c' 는 '변수 d' 의 address를 저장하게 됩니다.

또한 *c 는 'pointer 변수 c' 가 pointing(지정하는)하는 메모지 번지에 저장된 값을 의미하며,

printf("%d", *c) 와
printf("%d", d) 모두
는 10이라는 값을 출력합니다.

그렇다면, 이렇게 복잡한 pointer를 왜 이용할까요?

func1을 원하는 데로 만들기 위해서는 아래와 같이 pointer를 이용해야 합니다.

이러한 경우를 call by reference라고 합니다.
즉, pointer를 매개 변수로 함수가 호출되었다는 의미입니다.

func2(int a, int b, int *c)
{
    *c = a+b;
    return;
}

func2(e,f,&g);

라고 하면,
매개변수 c에는 g의 address가 전달되고,
*c 를 통해서 결과 값을 실제 g에 저장할 수 있습니다.

물론 위와 같은 함수는

int func3(int a, int b)
{
    return (a+b);
}

g = func3(a,b) 와 같이 이용될 수 있습니다.

이런 경우 복잡하게 pointer를 사용할 필요는 없죠.

하지만, 좀더 방어적으로 coding을 하려고 하면,
아래와 같이 overflow 유무도 같이 결과 값을 반환해야 합니다.
이런 경우 return을 통해서 sum결과와 overflow결과를 함께 반환하지 못합니다.
이때에는 반드시 pointer를 써서 결과를 전달하여야 합니다.

int func4(int a, int b, int *c)
{
    int sum;
    int isOverflow;

    sum = a+b;

    /* overflow check */
    ....

    if(isOverflow){ /* overflow 인 경우 */
        *c = 0;
    }
    else{ /* overflow가 아닌 경우 */
        *c = sum;
    }

    return isOverflow;
}

r = func4(e,f,&g);

if(r){
    /* Overflow...do domething. */
    ...
}

또한 pointer는 array(배열)의 전달에 가장 많이 이용이 됩니다.

다음 장에서는 Array와 Pointer에 대해서 알아보도록 하고,
이번 장은 이만 마치겠습니다.

Pointer는 C code의 가장 중요하고 기본적인 개념입니다.
사실 pointer는 자주 접하다 보면 금방 친숙해 집니다.
중요한 건 왜 pointer를 이용하는 지에 대해서 고찰을 해야 한다는 것입니다.
위의 예제에서 처럼 왜 pointer를 이용해야 하는지에 대해서 이해를 할 수 있으면,
좀더 쉽게 pointer를 이해할 수 있을 것 입니다.

Best Regards,
Wolverine


  Hit : 9837     Date : 2012/07/11 02:53