티스토리 뷰
2021.03.03.수
함수 포인터
✔ 함수를 정의하고 프로그램을 컴파일하면, 함수도 메모리 공간에 올라간다.
✔ 메모리에 올려진 함수를 실행하기 위해서는 그 위치를 알아야 한다.
✔ 배열과 마찬가지로 함수도 함수의 이름이 곧 메모리 주소를 의미한다.
✔ 그리고 함수가 호출되면 함수가 저장된 주소로 이동한다.
✔ 함수의 주소도 포인터에 저장할 수 있고, 포인터를 사용해 함수를 호출할 수도 있다.
int 함수명 (int, int); //함수 선언
int 함수포인터명 (int, int); //함수 포인터 선언
✔ 주소를 저장할 함수 포인터는 주소가 가리키는 것과 동일한 형태를 가리키도록 선언해야 한다.
✔ 함수의 형태는 매개변수의 개수와 자료형, 그리고 반환 값의 자료형으로 정의한다.
✔ 함수의 형태는 함수 선언부를 통해 알 수 있고, 함수 포인터의 선언부도 이와 동일해야 한다.
#include <stdio.h>
int sum(int, int);
int main(void){
int (*fp)(int, int); //함수 포인터 선언
fp=∑ //함수 포인터에 함수주소로 초기화
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=∑
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); = ∑ |
void 포인터 | (자료형 상관X) 주소 | void *vp; |
[참고] 한빛미디어-혼자 공부하는 C언어 유튜브 강의 / 엘리스 트랙-혼자 공부하는 C언어 / 길벗-C언어 코딩 도장 / 위키백과
'BackEnd > C' 카테고리의 다른 글
[21일차] 2. 동적 할당의 활용 / 명령행 인수 (0) | 2021.03.04 |
---|---|
[21일차] 1. 동적 메모리 할당 함수 (0) | 2021.03.04 |
[20일차] 4. 2차원 배열과 배열 포인터 (0) | 2021.03.03 |
[20일차] 3. 배열 요소의 주소와 배열의 주소 (0) | 2021.03.03 |
[20일차] 2. 이중 포인터의 활용 (0) | 2021.03.03 |