2012-01-23 6 views
14

가능한 중복 :
What is the point of function pointers?함수 포인터는 무엇을 사용합니까?

내가 실제 시나리오에서 함수 포인터가 사용되는 경우 이해하려고 노력하고 있습니다. 또한 누구나 함수 자체를 다른 함수의 인수로 전달해야하는 실질적인 예를 제공 할 수 있습니다.

+0

이것은 C#이지만 C/C++ 및 함수 포인터의 실용성에 대해서도 설명합니다. http://stackoverflow.com/questions/667410/the-benefits-of-using-function-pointers – Algorhythm

답변

18

함수 포인터는 callback mechanism을 만들고 다른 함수에 함수의 주소를 전달해야 할 때 유용 할 수 있습니다.

예를 들어 동적으로 호출 할 때 함수 배열을 저장하려는 경우에도 유용 할 수 있습니다.

8

한 가지 일반적인 용도는 callback function을 구현하는 것입니다.

qsort 라이브러리 기능을 사용하여 항목을 정렬 해보십시오. 마지막 매개 변수는 작성한 비교 함수 함수에 대한 포인터입니다.

5

매우 유용한 응용 프로그램으로 가장 먼저 떠오르는 것은 버튼입니다. 다음 코드를 보자

int buttonID = CreateButton ("Click Me!", 100, 100, 200, 100, onClick); 

이 폭 (200)과 높이 (100) 당신이 그것을 클릭 할 때마다와 (100100)에서 버튼을 만들 것입니다, 온 클릭 호출됩니다.

필자는 개인 Windows API 래퍼에서 비슷한 것을 사용합니다. 버튼 만들기 등이 훨씬 쉬워졌습니다.

3

음, # 1 재고 대답은 qsort입니다. qsort이 사용할 비교기 루틴은 함수 포인터로 전달됩니다. 다른 많은 "일반적인 알고리즘"함수는 유사한 방식으로 비교기를 사용합니다. 예 : 아마도 해시 테이블 구현은 해시 함수를 받아 들일 수 있습니다.

C 언어 GUI 툴킷 및 응용 프로그램 프레임 워크 (예 : Gnome/Gtk +/Glib)는 종종 타이머 또는 사용자 인터페이스 이벤트에 대한 "콜백"으로 함수 포인터를 허용합니다. (예 : "이 버튼을 클릭 할 때마다이 함수를 호출하십시오."또는 "...이 타이머가 만료 될 때마다 ...")

실제로 "C에서 대부분의"OOP 유사 "또는"이벤트 구동 "코드는 비슷한 이유. 함수 포인터에 대한 두 가지 용도가있다

4

:

  • 콜백 - 이벤트 핸들러 파서 전문화, 비교기 기능 전달을 위해 사용은 ...
  • 플러그인 및 확장 - 플러그인 또는 제공하는 기능에 대한 포인터 라이브러리 확장은 함수 식별자를 이름으로 취하여 함수 포인터를 반환하는 표준 함수 GetProcAddress, dlsym 또는 그와 비슷한 방식으로 수집됩니다. OpenGL과 같은 API에 절대적으로 중요합니다.
1

콜백을 함수에 전달할 때 사용할 수 있습니다. 예를 들어 qsort()을 사용하여 배열을 정렬 할 수 있습니다.이 기능을 사용하면 자신의 정렬 순서를 사용할 수 있다는 것을 의미하는 인수의 하나로서 비교 기능을한다 : 대부분의 경우

// All odd numbers are before even numbers 
int cmpoddeven(const void *xp, const void *yp) { 
    int x = *((int*) xp); 
    int y = *((int*) yp); 
    if(x == y) 
    return 0; 
    if(x % 2 == y % 2) { 
    return (x < y ? -1 : 1); 
    if(x % 2 == 1) 
    return -1; 
    return 1; 
} 

int main() { 
    int array[] = {1, 2, 3, 4, 5}; 
    // calling qsort with cmpoddeven as the comparison function 
    qsort(array, 5, sizeof(int), &cmpoddeven); 
    // array == {1, 3, 5, 2, 4}; 
} 
1

, 그것은 본질적으로 dependency inversion 일의 C의 방법입니다. 위키 기사는 다음과 같이 말합니다 :

가. 상위 모듈은 하위 모듈에 종속되어서는 안됩니다. 둘 다 추상화에 의존해야합니다. B. 추상화는 세부 사항에 의존해서는 안됩니다. 세부 사항은 추상화에 따라 달라야합니다.

qsort의 전형적인 예는 높은 수준의 정렬 기능은 데이터의 유형, 크기, 비교 방법에 의존하지 않는다는 점에서이를 수행

정렬된다. 따라서 만약 당신이 qsort() int의 배열이라면, 세부 사항은 sizeof(int)이고 비교 구현입니다. 추상화는 임의로 크기가 조정 된 요소의 배열이며 해당 형식의 요소를 비교하는 함수입니다.

다음을 참조하십시오 : Inversion of Control.

예를 들어 아무도 pthread_create()을 언급 한 것이 놀랍습니다.

종속성 반전으로 일반화 할 수없는 유일한 공통적 인 사용은 전환 불가능한 데이터 유형에서 스위치와 같은 흐름 제어를 구현하는 것입니다. 예를 들어 문자열을 전환하고 싶다면 정렬 된 문자열 키를 함수 포인터에 매핑하고 이진 검색을 수행합니다. 그것은 스위치처럼 O (1)가 아니지만, 맹목적으로 strcmp()를 큰 if-else에서 수행하는 것보다 낫습니다. 하지만 문자열을 토큰 화하고 실제 스위치를 사용하는 것보다 나은 것은 아닙니다.

4

콜백 루틴은 지금까지 제시된 가장 일반적인 시나리오 인 것으로 보입니다. 그러나 많은 다른 것들이 있습니다 ...

유한 상태 기계 (다차원) 배열 요소는 다음 상태를 처리/처리하는 루틴을 나타냅니다. 이것은 한 곳 (배열)에 FSM의 정의를 유지합니다.

활성화 기능 및 기능 비활성화는 기능 포인터를 사용하여 수행 할 수 있습니다. 유사하거나 별개의 기능을 사용하거나 사용하지 않도록 설정하려는 기능이있을 수 있습니다. if-else를 사용하여 코드를 채우고 혼란스럽게 만드는 대신 변수를 테스트하는 구문을 작성하는 대신 함수 포인터를 사용하도록 코드를 작성한 다음 함수 포인터를 변경/지정하여 기능을 활성화/비활성화 할 수 있습니다. 새로운 변종을 추가 할 경우 모든 if-else 또는 switch case를 추적 할 필요가 없습니다. 대신 새로운 기능을 사용하기 위해 함수 포인터를 업데이트하거나 이전 기능을 비활성화하십시오.

코드 혼잡 줄이기 이전 예제에서이 부분을 살펴 보았습니다. 같은

switch (a) { 
case 0: 
    func0(); 
    break; 
case 1: 
    func1(); 
    break; 
case 2: 
    func2(); 
    break; 
case 3: 
    func3(); 
    break; 
default: 
    funcX(); 
    break; 
} 

... 같은 예는

/* This declaration may be off a little, but I am after the essence of the idea */ 
void (*funcArray)(void)[] = {func0, func1, func2, func3, funcX}; 
... appropriate bounds checking on 'a' ... 
funcArray[a](); 

는 더 많은있다 ...에 간단하게 할 수 있습니다. 희망이 도움이됩니다.

+1

FWIW, 선언문 'void (* funcArray []) (void) = {func0, func1, func2 ...이어야합니다.};'('funcArray'는 함수에 대한 포인터의 배열입니다 ...). 선언 흉내 사용을 기억하십시오; 코드의 표현식이'funcArray [a]()'이면 선언문은 같은 방식으로 구성됩니다. –

+1

@ 존콘 - 많은 감사하겠습니다. 20 년 이상 C와 함께 작업 해 왔지만 함수 포인터 구문에 대해서는 여전히 혼란스러워합니다. 보통 나는 함수 포인터를 먼저 typedef'ing하고 나서 typedef'ed 변수의 배열을 선언하는 더 쉬운 (나를 위해) 경로를 선택한다. – Sparky

+0

@ Sparky typedef에 관한 합의. 함수 포인터의 배열이나 함수 포인터에 대한 포인터와 같은 상황을 훨씬 쉽게 읽을 수 있습니다. –

관련 문제