문타쿠, 공부하다.
[독하게 시작하는 C 프로그래밍] 섹션 21. 함수에 대한 고급 이론 본문
함수 포인터
- 함수의 이름(=주소 상수)을 저장할 수 있는 포인터
- 함수호출 연산자의 피연산자가 될 수 있음
- 반환자료형(호출규칙 *변수명)(매개변수) 형식으로 선언
- 호출규칙은 생략 가능
- 32비트 호출규칙: __cdecl(C언어 기본), __stdcall, __fastcall
- 64비트 호출규칙: __fastcall
#include <stdio.h>
double Average(int num1, int num2, int num3)
{
double avg = (num1 + num2 + num3) / 3.0;
return avg;
}
int main(void)
{
double(*myAverage)(int, int, int) = Average;
printf("나의 평균 점수는 %.2f점입니다.\n", Average(88, 99, 100));
printf("나의 평균 점수는 %.2f점입니다.\n", myAverage(88, 99, 100));
return 0;
}
역호출 구조
Call back 구조
- 함수가 호출하는 것이 아니라 호출되는 구조
- 함수의 이름(주소 상수)을 라이브러리나 프레임워크에 전달하면 그 내부에서 호출되는 구조 -> 매개변수가 함수 포인터인 함수가 필요
- 호출 시점과 횟수를 정확히 특정하기 어려운 경우가 많음
정렬 알고리즘 중에 가장 빠른 퀵 정렬 qsort() 함수를 사용한 예시
#include <stdlib.h>
qsort(정렬할 값의 주소, 요소의 개수, 요소의 크기, 기준함수);
기준함수가 return 한 값이 양수이면 두 수의 자리를 바꾸고, 음수이면 자리를 바꾸지 않음
#include <stdio.h>
#include <stdlib.h>
// 기준함수 1: 오름차순
int Compare1(const int* pParam1, const int* pParam2)
{
/* pParam1이 pParam2보다 크면 return 값이 양수 -> 자리 바꿈
* pParam1이 pParam2보다 작으면 return 값이 음수 -> 자리 안바꿈 */
return *pParam1 - *pParam2;
}
// 기준함수 2: 내림차순
int Compare2(const int* pParam1, const int* pParam2)
{
/* pParam2가 pParam1보다 크면 return 값이 양수 -> 자리 바꿈
* pParam2가 pParam1보다 작으면 return 값이 음수 -> 자리 안바꿈 */
return *pParam2 - *pParam1;
}
// 기준함수 1의 오름차순 정렬을 아래와 같이 표현 가능
int Compare1_2(const int* pParam1, const int* pParam2)
{
if (*pParam1 > *pParam2)
return 1;
else
return -1;
}
// 기준함수 2의 내림차순 정렬을 아래와 같이 표현 가능
int Compare2_2(const int* pParam1, const int* pParam2)
{
if (*pParam2 > *pParam1)
return 1;
else
return -1;
}
int main(void)
{
int List[5] = { 20, 50, 40, 10, 30 };
printf("정렬 전 List\n");
for (int i = 0; i < 5; i++)
printf("%d ", List[i]);
printf("\n\n");
printf("오름차순 정렬\n");
qsort(List, 5, sizeof(int), Compare1);
for (int i = 0; i < 5; i++)
printf("%d ", List[i]);
printf("\n\n");
printf("내림차순 정렬\n");
qsort(List, 5, sizeof(int), Compare2);
for (int i = 0; i < 5; i++)
printf("%d ", List[i]);
printf("\n");
return 0;
}
Lookup 테이블과 역호출 결합
#include <stdio.h>
typedef enum MOVE { UP, DOWN, LEFT, RIGHT, QUIT } MOVE;
int GoUp(int nParam)
{
puts("Go Up");
return 0;
}
int GoDown(int nParam)
{
puts("Go Down");
return 0;
}
int GoLeft(int nParam)
{
puts("Go Left");
return 0;
}
int GoRight(int nParam)
{
puts("Go Right");
return 0;
}
MOVE GetInputFromClient()
{
// TODO
return DOWN;
}
int main(void)
{
int(*functionArray[4])(int) = { GoUp, GoDown, GoLeft, GoRight };
MOVE act = 0;
while ((act = GetInputFromClient()) != QUIT)
{
/*switch (act)
{
case UP:
functionArray[UP](0);
break;
case DOWN:
functionArray[DOWN](0);
break;
case LEFT:
functionArray[LEFT](0);
break;
case RIGHT:
functionArray[RIGHT](0);
break;
default:
break;
}*/
// 위의 switch case문과 같은 역힐을 하는 더 효율적인 코드
functionArray[act](0);
}
return 0;
}
'C언어 > 독하게 시작하는 C 프로그래밍' 카테고리의 다른 글
[독하게 시작하는 C 프로그래밍] 섹션 20. 전처리기 (0) | 2023.12.02 |
---|---|
[독하게 시작하는 C 프로그래밍] 섹션 19. 변수와 상수 고급 이론 (Part 4. 고급 이론) (0) | 2023.12.01 |
[독하게 시작하는 C 프로그래밍] 섹션 18. 파일 입/출력 (0) | 2023.11.30 |
[독하게 시작하는 C 프로그래밍] 섹션 17. 구조체와 공용체 (0) | 2023.11.26 |
[독하게 시작하는 C 프로그래밍] 섹션 16. 함수 응용 (0) | 2023.11.26 |