티스토리 뷰

2021.03.03.수

함수 포인터

✔  함수를 정의하고 프로그램을 컴파일하면, 함수도 메모리 공간에 올라간다.

✔  메모리에 올려진 함수를 실행하기 위해서는 그 위치를 알아야 한다.

✔  배열과 마찬가지로 함수도 함수의 이름이 곧 메모리 주소를 의미한다.

✔  그리고 함수가 호출되면 함수가 저장된 주소로 이동한다.

✔  함수의 주소도 포인터에 저장할 수 있고, 포인터를 사용해 함수를 호출할 수도 있다.


int 함수명 (int, int);	 //함수 선언
int 함수포인터명 (int, int);	 //함수 포인터 선언

✔  주소를 저장할 함수 포인터는 주소가 가리키는 것과 동일한 형태를 가리키도록 선언해야 한다. 

✔  함수의 형태는 매개변수의 개수와 자료형, 그리고 반환 값의 자료형으로 정의한다.

✔  함수의 형태는 함수 선언부를 통해 알 수 있고, 함수 포인터의 선언부도 이와 동일해야 한다.


#include <stdio.h>

int sum(int, int);  

int main(void){
  int (*fp)(int, int);		//함수 포인터 선언
  fp=&sum;			//함수 포인터에 함수주소로 초기화			
  int result = fp(10,20);	//함수 포인터로 함수 실행 후 반환값을 result 변수에 저장
  printf("result : %d\n", result);  
  return 0;
}

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

✔  sum함수의 주소를 저장할 함수 포인터는 위와 같이 선언하고 사용할 수 있다.

✔  이때, 반드시 함수 포인터 변수명을 별표와 함께 괄호로 묶어야 한다.

✔  괄호가 없으면 주소를 반환하는 함수의 선언이 되므로 주의하자.

 

✔  함수 포인터를 선언한 후에 함수명을 저장하면, 포인터를 함수처럼 쓸 수 있다.

✔  이 때 함수 포인터는 일반적인 포인터와 달리 간접 참조 연산자가 필요 없이 바로 함수 호출이 가능하다. 

 

 

함수 포인터의 활용
#include <stdio.h>

int sum(int a, int b) { return (a+b); };  
int avg(int a, int b) { return ((a+b)/2); };  

int main(void){
  int res;
  int (*fp)(int, int);
  
  //함수 포인터에 sum함수의 주소로 초기화 (주소연산자를 사용해 초기화)
  fp=&sum;			
  res = fp(10,20);
  printf("10 + 20 = %d\n", res);  
  
  //함수 포인터에 avg함수의 주소로 초기화 (함수명으로 초기화)
  fp=avg;			
  res = fp(10,20);
  printf("(10 + 20)/2 = %d\n", res);  
  
  return 0;
}

✔  함수 포인터는 함수 선언부의 형태와 동일하게 선언하면, 기능과 상관없이 모든 함수의 주소를 저장할 수 있다.

✔  따라서 형태가 같은 다양한 기능의 함수를 선택적으로 호출할 때 사용한다.


#include <stdio.h>

void func(int (*fp)(int, int));   

int sum(int a, int b) {return (a + b);}
int mul(int a, int b) {return (a * b);}
int max(int a, int b) {return a > b ? a : b;}

int main(void){
  int sel;                  
  printf("1.두 정수의 합\t2.두 정수의 곱\t3.두 정수 중에서 큰 값 계산\n");     
  printf("원하는 연산을 선택하세요 : ");
  scanf("%d", &sel);      

  switch (sel){
    case 1: func(sum); break;        // 1이면 func에 덧셈 기능 추가
    case 2: func(mul); break;        // 2이면 func에 곱셈 기능 추가
    case 3: func(max); break;        // 3이면 func에 큰 값 구하는 기능 추가
  }
  return 0;
}

void func( int(*fp)(int,int) ){
  int a, b;
  printf("두개의 정수 입력 : ");
  scanf("%d %d", &a, &b);
  printf("결과 : %d\n",fp(a,b));

}

✔  함수 포인터를 함수의 매개변수로 사용할 수 있으며, 함수호출마다 함수 포인터에 저장할 함수를 지정하여 호출할 수 있다.

 

 

void 포인터
void *vp;

int a = 10;
vp = &a;

double b = 3.14;
vp = &b;

✔  void 포인터는 어떤 형태의 주소든 저장할 수 있다.

✔  자료형을 알 수 없기 때문에, 간접 참조 연산이나 정수를 더하는 포인터 연산이 불가능하다.

✔  형 변환을 통해 포인터 변수의 자료형을 일시적으로 바꾸어 간접 참조 연산이나 주소값의 연산을 할 수 있다.

 

void *vp;

int a = 10;
vp = &a;
printf("%d", *(int*)vp);	//10

✔  형변환을 통해 자료형을 일시적으로 바꾸어, 간접 참조 연산자를 사용하여 가리키는 주소의 값에 접근할 수 있다.

 

#include <stdio.h>

int main(void)
  {
  int arr[3] = {1,2,3};
  void *vp = arr;

  for(int i=0; i<3; i++){
    // printf("%d\t", vp[i]);		//ERROR!
    printf("%d\t", *((int*)vp+i));	// 1  2  3
  }

  return 0;
}

✔  형 변환을 통해 자료형을 일시적으로 바꾸어, 주소 값의 연산이 가능하다.

 

 

 

다양한 포인터의 형태 정리
저장 공간 저장할 값의 형태 (예)
포인터 변수 주소   int *p  = &arr[1];
이중 포인터 변수 포인터 변수의 주소   int **pp = &p;
포인터 배열 포인터 변수   int *arr_p[3] = { &arr1[0], &arr1[1], &arr1[2]} ;
배열 포인터 2차원 배열명
2차원 배열의 부분 배열명
  int (*arr_p)[3] = arr2[0] ;
함수 포인터 함수의 주소 / 함수명   int (*fp)(int, int); = &sum;
void 포인터 (자료형 상관X) 주소   void *vp;

 

 

 

 

 

[참고] 한빛미디어-혼자 공부하는 C언어 유튜브 강의 / 엘리스 트랙-혼자 공부하는 C언어 / 길벗-C언어 코딩 도장 / 위키백과

댓글
«   2025/05   »
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 31
최근에 올라온 글
글 보관함
Total
Today
Yesterday