Notice
Recent Posts
Recent Comments
Link
«   2025/07   »
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
Tags
more
Archives
Today
Total
관리 메뉴

문타쿠, 공부하다.

[독하게 시작하는 C 프로그래밍] 섹션 21. 함수에 대한 고급 이론 본문

C언어/독하게 시작하는 C 프로그래밍

[독하게 시작하는 C 프로그래밍] 섹션 21. 함수에 대한 고급 이론

개발새발 문타쿠 2023. 12. 3. 04:57

함수 포인터

  • 함수의 이름(=주소 상수)을 저장할 수 있는 포인터
  • 함수호출 연산자의 피연산자가 될 수 있음
  • 반환자료형(호출규칙 *변수명)(매개변수) 형식으로 선언
    • 호출규칙은 생략 가능
    • 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;
}