[C언어] 응용포인터

이가영·2023년 10월 22일
0

C언어

목록 보기
16/16

포인터의 핵심 정리

  • 포인터는 다음의 두 가지만 이해하면 응용이 가능하다
  1. 포인터가 가리키는 자료형은 무엇인가? -> "실체가 무엇인가?"
int val;
&val -> int형 변수
포인터의 &val은 int형을 가리킨다.
double val
&val -> double형 변수
포인터 &val은 double형을 기리킨다.
  1. 포인터는 같은 자료형을 가리키는 포인터변수에 저장해야 한다.
int * ip;
가리키는 자료형  ip=포인터 변수

ip=&val; //포인터를 포인터변수에 대입
-> 가리키는 자료형은 모두 int형으로 같다.

다중 포인터

  • 포인터변수도 하나의 기억공간이므로 포인터(물리적 주소)를 구할 수 있다.
    포인터변수의 포인터 -> 이중포인터
int *ip;
&ip       ->  (int *)형 변수  //포인터 &ip는 (int*)형을 가리킨다
이중포인터        포인터변수
  • 이중포인터로 변수를 참조할 때는 참조연산자를 두 변 사용해야 한다.

이중포인터변수

  • 이중포인터 또한 하나의 포인터이므로 포인터변수에 저장하여 사용한다.
int *ip;
int **ipp; //integer포인터에 주소값을 저장시킬 애가 ipp이다.
가리키는 자료형 / ipp는 포인터변수다. / 변수의 이름

ipp = &ip; //이중포인터를 이중표인터변수에 대입
-> 가리키는 자료형은 모두 (int *)형으로 같다
  • 이중포인터변수도 참조연산자를 두 번 사용하여 변수를 참조한다.
int val = 10;
int *ip;  //포인터변수
int **ipp;  //이중포인터변수
int = &val;  //주소값 저장
ipp = &ip;
printf("%d\n", **ipp);

*(*ipp) => *(100) => 10

이중포인터변수의 사용 예

  • 두 포인터변수의 값을 바꾸는 함수를 만들어보자
char *ap = "success";
char *bp = "failure";
-> 변경하지 못하는 임시데이터메모리에 success, failure 생기고, 여기에 있는 주소값이 success에 치환돼서 컴파일된다.

함수의 호출 -> exchange ptr(&ap, &bp); //이중포인터를 전달인자로 준다
//exchange함수에 ap와 bp의 주소값을 줌 -> 이 값을 exchange_ptr이라는 애가 값을 바꾸므로
함수의 선언 -> void exchange_ptr(char **app, char **bpp);
//이중포인터가 전달인자로 넘어오므로 매개변수로 이중포인터 변수를 선언
함수가 호출된 후 -> 

  • 함수 안에서는 임시 포인터변수를 선언하여 ap, bp의 값을 바꾼다.
char *tp;  //임시 포인터변수의 선언

함수를 사용하여 포인터변수의 값을 바꾸는 프로그램

#include <stdio.h>

void exchange_ptr(char **, char **);  //함수의 선언
int main()
{
	char *ap = "success";
    char *bp = "failure";
    printf("*ap -> %s, bp -> %s\n", ap, bp);  //바꾸기 전의 문자열 출력
    exchange_ptr(&ap, &bp);  //함수의 호출
    printf("ap -> %s, bp -> %s\n", ap, bp);  //바꾼 후에 문자열 출력
    return 0;
}

void exchange_ptr(char **app, char **bpp) //함수의 정의
{
	char *tp;  //임시 포인터변수
    tp=*app;
    *app=*bpp;  //메인함수에 있는
    *bpp=*tp;   //ap, bp의 값을 바꾼다.
}
출력결과
ap -> success, bp -> failure
ap -> failure, bp -> success

연습문제

  • 포인터 배열에 저장된 문자열을 출력하는 프로그램

    char spp** -> 이 매개변수를 어떻게 만들지를 이해해야 함!!

배열 포인터

배열명의 정체

  • 배열명은 첫 번째 배열요소를 가리키는 포인터의 기능을 한다.
int nums[5] = {10, 20, 30, 40, 50};
int *ip=nums;  //배열명은 포인터이므로 포인터변수에 저장
printf("%d\n", *nums);  //첫 번째 기억공간을 참조하여 10이 출력
printf("%d\n", *(nums+4));  //nums의 값이 100이면 116번지를 참조
nums      10  20  30  40  50------| 배열명은 첫번째 배열요수를 가리키는 포인터
  • 배열의 기억공간 전체를 나타내는 논리적 변수의 기능을 한다.
    -> 논리적 변수(상수)이므로 -> 직접 데이터를 저장할 수는 없으나
    응용 자료형으로서 -> 변수가 가지는 형태와 그기에 대한 정보를 가진다.

배열포인터가 가리키는 것은?

  • 배열포인터는 배열명에 주소연산을 수행하면 구해진다.
    -> 이 때 배열명은 논리적변수의 기능이며 그 배열 전체를 가리키는 포인터가 구해진다.
int ary[5];
&ary    -->    int  int  int  int  int
배열포인터        배열의 전체를 가리킨다

-> 배열포인터에 정수값을 더하면 배열 전체의 크기를 곱해서 더해주게 된다.

2차원 배열의 배열명은 배열포인터이다

2차원 배열에서 배열명으로 기억을 참조하는 공간

  • 1차원의 물리적 기억공간을 행렬의 2차원 구조로 참조할 수 있는 것은 2차원 배열의 배열명과 부분배열명이 각각 배열포인터와 포인터로서 적절한 기능을 수행하기 때문이다.

2차 배열포인터변수

  • 2차 배열포인터를 저장 -> 배열포인터변수
ap에는 int[4] type의 배열 포인터가 저장된다.

-> 배열포인터변수가 2차원 배열의 배열명을 저장하면 2차원 배열처럼 사용된다.

int any[3][4]={{1,2,3,4}, {5,6,7,8},{9,10,11,12}};
int (*ap)[4];int i, j;
ap=ary;  //배열명을 배열포인터변수에 저장
for(i=0; i<3; i++)
{
	for(j=0; j<4; j++)
    {
		printf("%5d", ap[i][j]); //ap를 배열명처럼 사용
    }
    printf("\n");
}
출력결과
1   2   3   4  
5   6   7   8
9   10  11  12

배열 포인터

  • 해석 방법 : 단항 -> 후치 -> 근치
int ap[][4]
4   1 2  3

연습문제

  • 5개의 문자열을 2차원 배열에 입력 받아 출력하는 프로그램
    단,
  1. 2차원 문자배열은 메인함수에서 선언
  2. 입출력 작업은 각각 함수를 호출해서 수행
  3. 문자열의 길이는 최대 80자로 제한

함수 포인터

  • 함수포인터는 함수의 이름이다.
    -> 함수명은 함수의 정의가 있는 메모리의 위치값이며 함수를 가리킨다.

-> 함수명이 포인터라는 증거는 참조연산자를 사용하면 알 수 있다.

(*sum)(10, 20); //10과 20을 전달인자로 주고 sum함수를 호출한다.
(함수를 참조한 후에 호출해야 하므로 참조연산에 괄호를 사용한다.)

함수포인터변수

  • 함수 포인터가 가리키는 자료형은 함수의 형태이다.
    -> 함수의 형태를 매개변수의 개수와 형태, 리턴값의 형태이다.
  • 함수포인터를 함수포인터변수에 저장하여 호출할 수 있다.
fp(10, 20); //= sum(10, 20);

함수포인터변수로 sum함수를 호출하는 프로그램


함수포인터는 어디에 사용?

  • 함수포인터변수는 함수의 형태만 같으면 기능과 상관없이 모든 함수포인터를 저장할 수 있다.
int sum(int, int); //두 정수값을 더해서 리턴하는 함수
int mul(int, int); //두 정수값을 곱해서 리턴하는 함수
int max(int, int); //두 정수값 중에서 큰 값을 리턴하는 함수
-> 세 개 모두 형태가 같다
int (*fp)(int, int); -> fp = sum; 
                        fp = mul;  // 모두 사용 가능
                        fp = max;  
  • 형태가 같은 다양한 기능의 함수를 선택적으로 호출하는데 사용할 수 있다.

  • 다음과 같은 기능을 수행하는 함수를 만들자

    -> func함수에서 2번 연산과정은 함수를 호출할 때 필요한 연산이 수행되도록 만들자

func함수를 사용한 프로그램

연습문제

  • exchange함수와 func함수를 만들어 프로그램을 완성
    -> func함수는 전달인자로 받은 두 값을 출력한 후에 exchange함수를 사용하여 두 값을 바꾸고 다시 출력
    -> exchange함수는 포인터를 전달인자로 받아서 그들이 가리키는 두 값을 바꾼다.

void 포인터

  • 가리키는 자료형에 대한 정보가 없는 포인터이다.
int a; //int형 변수 선언
(void*) &a; //int형 변수의 포인터를 void 포인터로 강제 형변환
  • void포인터변수는 가리키는 자료형이 정해져 있지 않으므로 모든 포인터를 저장할 수 있다.
void * vp;
가리키는 자료형이 정해져 있지 않다/vp=포인터변수/변수의 이름
int in;  //int형 변수
double db; //double형 변수
void *vp; //void포인터 변수
vp=&in; //int형 변수의 포인터를 저장할 수 있고
vp=&db; //double형 변수의 포인터도 저장할 수 있다.


#include <string.h>도 있어야 함
type은 자료형 구분을 위한 매개변수

profile
gy’s portfolio

0개의 댓글