[C언어] #7 함수 포인터

Ilhoon·2022년 2월 18일
1
post-thumbnail

함수 포인터

함수 자체를 어디다 저장해 둔 뒤 매개변수로 전달 할 수는 없을까?

  • 함수를 호출하면 어떤 일이 일어나지?

  • 어셈블리어를 까보면...컴퓨터가 하는일은 함수를 호출했을 때 그 함수가 시작되는 주소로 점프

  • 이 주소 : 함수가 시작되는 주소는 컴파일 도중에 정해지는 주소. (실행중에 바뀌는 주소는 아니다)

  • 하지만 함수가 반환해서 돌아가는 주소는 실행도중에 변경된다.

    • 어디서 호출했느냐에 따라서 달라진다.
    // 함수 호출시 스택메모리 구조
    
    |------호출자 스택프레임------|
    |----00E211AB(돌아갈주소)----|
    |----호출된함수 스택프레임-----|
    |---------------------------|
  • 함수를 실행시키려면? 함수가 시작하는 메모리 주소를 알면된다!

  • 즉 함수포인터는 함수가 시작하는 코드 주소를 저장하는 포인터 변수


함수 포인터의 자료형

매개변수로 전달되는 함수는 다음과 같은 내용도 포함해야한다.

  • 자신이 반환하는 자료형
  • 자신이 받는 매개변수의 자료형
double add(double x, double y){
    return x + y;
}

/*
함수 포인터의 선언
1. func는 변수명 (포인터 변수)
2. 변수에 저장되는 주소는 반환타입 double, 매개변수 (double, double)의 함수의 시작 주소
3. 시작주소를 가져올 함수는 바로 add (괄호 생략해서 대입)
*/
double (*func)(double, double) = add;

// 결과값은 op1 + op2 반환 --> func에 대입한 이후 함수처럼 똑같이 사용가능하다.
result = func(op1, op2);

함수포인터 매개변수로 사용

double calculate (double x, double y, double (*func)(double, double))
{
    return func(x, y);
}

result = calculate(op1, op2, add);

함수 포인터의 배열도 가능

int add(int x, int y){
    return x + y;
}
int sub(int x, int y){
    return x - y;
}
int mul(int x, int y){
    return x * y;
}
int div(int x, int y){
    return x / y;
}

int (*ops[])(int, int) = {add, sub, mul, div};



함수 포인터의 용도

  • 어떤 조건에 따라 실행되는 함수를 다르게 하고 싶을 때 (반환형, 매개변수 타입이 동일)

  • C# 에서 delegate도 사실 함수 포인터

  • JavaScript에서도 비슷한 개념으로 사용

    • var bar = function() {alert("Hello"); }
      var foo = bar;
      bar = function() {alert("Good Bye"); }
      foo(); 	// Hello 출력 --> foo에는 이전 함수의 시작주소가 저장되어있다.
  • 퀵정렬 함수

    • /*
      <stdlib.h>안에 있는 표준 라이브러리 함수
      정렬할 배열의 시작주소, 요소수, 각요소의 크기, 정렬기준
      */
      void qsort(void *ptr, size_t count, size_t size, int (*comp)(const void*, const void*));

void*

모든 포인터를 대입가능한 범용적 포인터

데이터 크기를 알아야하는 연산은 불가 (역참조, 포인터 산술연산 등)

profile
꾸준하게!

0개의 댓글