wau2380's playground

학생을 위한 C 언어 1. 포인터 본문

학생을 위한 C/포인터

학생을 위한 C 언어 1. 포인터

wau2380 2021. 7. 9. 11:23


들어가기 전에

여러분들이 이 글을 보고 있다면 여태까지 C언어를 열심히 공부하셨다는 증거입니다. (정말 수고하셨어요!)

포인터는 C언어의 심장이라고 말할 수도 있겠습니다.
고급언어로 유명한 파이썬, 자바도 포인터를 사용합니다. (내부적으로 감추고 있습니다.)
그러므로 포인터를 배우고 사용할 수 있다는 것은 앞으로 배울 다른 프로그래밍 언어를 더 쉽게 배울 수도 있습니다.

그리고 "포인터를 왜 배우지?"라고 묻는 친구들이 종종 있습니다. 굳이 말하자면 아래와 같습니다.
간결하고 효율적인 표현과 처리가 가능하고, 복잡한 자료 구조(배열, 구조체 등)와 함수의 쉬운 접근이 가능하다

포인터를 이해하기 위해서는 열린 마음으로 받아들이면 됩니다 ^^


1. 포인터(Pointer)란 무엇일까?

지금까지 C에서는 변수에 정수, 실수, 문자열 등을 저장했습니다.
그러면 메모리 주소도 저장할 수 있지 않을까요?

메모리의 주소를 저장하는 변수를 포인터라고 부릅니다!


메모리 주소는 OS가 임의로 정해요!
그림만 봐서는 확 와닿지는 않죠? 예제 코드를 봅시다!

#include <stdio.h>

int main()
{

int a; 

int *p = NULL; //정수형 포인터 변수 선언

p=&a; // p에 a의 메모리 주소 저장

printf("a의 주소는 %d 번지 입니다. \n",&a); 
//a의 주소 출력
printf("p의 저장된 주소는 %d 번지 입니다.\n ",p);
//p에 기록된 값 출력하기
return 0;
}


한번 따라 써봅시다!

리고 포인터는 시작 주소와 함께 어떻게 해석해야 할지에 대한 정보도 가지고 있습니다.
*주의 (바라보는 각도에 따라 값이 달라져요 ex) char, float, unsigned int, signed int)


2.void 포인터(Pointer)

void는 "없다" , "비어있다"라는 의미입니다.

void* p는 시작 주소 (p가 원래 가지는 저장된 주소)만 있고, 해석 방법이 정해지지 않은 포인터입니다.
그러므로 사용할 때마다, 어떻게 해석할 것인지를 정해줘야 합니다.

예제 코드를 봅시다.

#include <stdio.h>

int main()
{
    int i=10;
   
    void*vp =NULL;
    vp = &i;
    
    printf("메모리 주소는 : %d\n",&i);
    printf("정수형으로 해석한 값 : %d\n",*( (int *)vp)); 
    //정수형으로 해석하겠다고 알려줌
    return 0;
}


위에서 말했듯이 void형 포인터는 어떻게 해석할지 정해주어야 합니다.



3. 포인터를 이용하여 메모리에 접근하기

그렇다면 포인터를 이용해서 저장된 값을 바꾸거나 추가할 순 없을까요?
당연히 가능하죠!! 아래 코드를 봅시다

#include <stdio.h>

int main(){

    int a =123;
    int *p = NULL;

    p = &a;
    printf("%d번지의 저장된 값은 %d입니다.\n",p,*(p));
    *(p) = 100; //p에 기록된 주소에 접근
    printf("a에 기록된 값은 %d 입니다.\n",a);

return 0;
}


결과는 여러분들이 한번 생각해 보세요!



4.함수 포인터(Pointer)

변수형 포인터만 소개하면 함수형 포인터가 슬퍼하겠죠?😭😭😭

함수형 포인터는 말그대로 함수의 주소를 저장합니다.
따라서 함수의 주소를 담을수 있는 변수를 만들수 있는데 이를 "함수 포인터"라고 합니다.
(함수는 함수의 이름의 주소가 담겨있어요~~)

아래 코드를 이용하여 함수의 주소를 출력해봅시다!

#include <stdio.h>
void A(){


}
int main()
{

    printf("A함수의 주소는 %d 입니다",A);

return 0;
}


그러면 함수의 주소를 저장하는 "함수포인터"를 본격적으로 만들어 봅시다

아래코드를 통하여 규칙을 알아봅시다!

#include <stdio.h>

void A(){ //반환값과 매개변수가 없어요!

}

int mul(int a,int b){ //반환값과 매개변수가 있어요!
return a*b;
}

int main()
{
    int (*fmul) (int,int); //반환값과 매개변수가 있는 포인터 선언
    fmul = mul;

    void (*fA) (); //반환값과 매개변수가 없는 함수 포인터 선언
    fA = A;

    printf("A함수의 주소는 %d\n", A);
    printf("fA에 기록된 주소는 %d\n",fA);

    printf("B함수의 주소는 %d\n", mul(3,5));
    printf("fB에 기록된 주소는 %d\n",fmul(3,5));

return 0;
}


규칙은 다음과 같아요. 반환타입(int,void 등) *변수이름 (매개변수 타입 )
(이제 포인터로 전역변수를 선언하지 않고도 함수를 마음껏 건들수 있어요!)
그런데 너무 정의하는게 힘들지 않나요?

typedef를 이용하여 함수 포인터의 타입을 선언할 수 있습니다!


5.함수포인터 타입 만들기

지금까지 함수 포인터를 만들 때 int (*fp)(int, int);처럼 일일이 반환값 자료형과 매개변수 자료형을 명시해주었습니다. 이런 방식을 full pointer type 이라고 하는데 사용하기가 상당히 번거롭고, 이때는 typedef로 별칭(별명)을 정의하면 함수 포인터를 매번 만들지 않아도 됩니다 !

typedef int (*funcp) (int,int); funcp A,B,C,D;

둘다 같은 의미입니다!
int (*A) (int,int); int (*B) (int,int); int (*C) (int,int); int (*D) (int,int);


정리

1. 포인터는 메모리 주소를 가지고 있는 변수
2.void형은 해석 방법이 정해져 있지 않음
3. 포인터로 안에 있는 값과 주소 변경 가능
4.함수 포인터는 함수의 주소를 가지는 변수
5.typedef로 함수포인터를 쉽게 정의 가능

출처 입력

수고하셨습니다 ~

Created by Pixochris - Freepik.com(Created by flaticon - Freepik.com)



'학생을 위한 C > 포인터' 카테고리의 다른 글

학생을 위한 C 언어 2.포인터와 배열  (0) 2021.06.19