C의 함수 포인터에 대한 typedef 이해
다른 사람의 코드를 읽을 때는 항상 당황하고 있습니다.다른 사람의 코드에는 인수와 함수의 포인터가 포함되어 있습니다.조금 전에 C로 표기된 수치 알고리즘을 이해하려고 하다가, 그러한 정의에 도달하는 데 시간이 걸렸던 것으로 기억합니다.그래서, 함수에 대한 포인터(실행 및 실행 안 함)를 위한 좋은 타이피프를 작성하는 방법에 대한 조언과 생각을 공유해 주실 수 있나요?감사합니다!
「 」에 대해 .signal()
C 、 C 、 C 、 C c c c :
extern void (*signal(int, void(*)(int)))(int);
- 의 인수를 하지 않는 및 포인터 두 를 인수로서 반환하지 않습니다. - 반환하다.signal()
하지 않습니다는 정수를 인수로 사용하는 함수에 포인터를 반환하고 아무것도 반환하지 않습니다.
다음과 같이 쓸 경우:
typedef void (*SignalHandler)(int signum);
을 하면 됩니다.signal()
같이요.
extern SignalHandler signal(int signum, SignalHandler handler);
이것은 같은 것을 의미하지만, 일반적으로 읽기 쉬운 것으로 간주됩니다.에 '이러다'가 이 더 합니다.int
a. a. a.SignalHandler
a를 .SignalHandler
.
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★ 신호 하여 신호 쓸수.SignalHandler
typedef
함수의 정의에서.
저는 여전히 함수 포인터를 호출하는 것을 선호하는 구식 사용자입니다.
(*functionpointer)(arg1, arg2, ...);
최신 구문에서는 다음 항목만 사용합니다.
functionpointer(arg1, arg2, ...);
알 것 는 변수가 되어 있는 .다음에 따라서는 안 된다라는 함수를 보다요.변수가 초기화되어 있는 곳을 찾는 것이 좋습니다.functionpointer
.
Sam 코멘트:
나는 이 설명을 전에 본 적이 있다.그리고 지금과 마찬가지로 두 진술의 연관성을 파악하지 못했다고 생각합니다.
extern void (*signal(int, void()(int)))(int); /*and*/ typedef void (*SignalHandler)(int signum); extern SignalHandler signal(int signum, SignalHandler handler);
아니면 두 번째 버전을 만들기 위해 사용할 수 있는 기본 개념은 무엇입니까?"Signal Handler"와 첫 번째 typedef를 연결하는 기본 요소는 무엇입니까?여기서 설명되어야 할 것은 typedef가 실제로 여기서 하고 있는 것이라고 생각합니다.
다시 해 봅시다.이 중 첫 번째 항목은 C 표준에서 바로 들어왔습니다. 다시 입력하고 괄호를 올바르게 입력했는지 확인합니다(수정할 때까지가 아닙니다.기억제).
이 점을 해 주세요.typedef
에 타입의 에일리어스가 도입되었습니다.는 래래 so so so so so so so so 。SignalHandler
을 사용하다
정수를 인수로 사용하고 아무것도 반환하지 않는 함수에 대한 포인터.
nothing 은 returns nothing으로 되어 void
; 정수인 인수는 (신뢰할 수 있는) 자명합니다.다음 표기법은 C가 지정된 인수를 사용하여 지정된 유형을 반환하는 기능에 대한 포인터의 철자를 단순하게(또는 그렇지 않은) 것입니다.
type (*function)(argtypes);
신호 핸들러 타입을 작성한 후 이를 사용하여 변수를 선언할 수 있습니다.예를 들어 다음과 같습니다.
static void alarm_catcher(int signum)
{
fprintf(stderr, "%s() called (%d)\n", __func__, signum);
}
static void signal_catcher(int signum)
{
fprintf(stderr, "%s() called (%d) - exiting\n", __func__, signum);
exit(1);
}
static struct Handlers
{
int signum;
SignalHandler handler;
} handler[] =
{
{ SIGALRM, alarm_catcher },
{ SIGINT, signal_catcher },
{ SIGQUIT, signal_catcher },
};
int main(void)
{
size_t num_handlers = sizeof(handler) / sizeof(handler[0]);
size_t i;
for (i = 0; i < num_handlers; i++)
{
SignalHandler old_handler = signal(handler[i].signum, SIG_IGN);
if (old_handler != SIG_IGN)
old_handler = signal(handler[i].signum, handler[i].handler);
assert(old_handler == SIG_IGN);
}
...continue with ordinary processing...
return(EXIT_SUCCESS);
}
신호 핸들러에서의 사용을 피하는 방법에 대해 주의해 주십시오.
코드 컴파일을 깔끔하게 하기 위해 필요한 4개의 표준 헤더를 생략한 것 외에 여기서 무엇을 했습니까?
처음 두 함수는 하나의 정수를 사용하고 아무것도 반환하지 않는 함수입니다. 중 는 실제로 exit(1);
그러나 다른 하나는 메시지를 인쇄한 후 되돌아옵니다.C 규격에서는 신호 핸들러 내부에서 많은 작업을 수행할 수 없습니다.POSIX는 허용 범위 내에서 좀 더 관대하지만 공식적으로 콜을 허가하지는 않습니다.fprintf()
수신한 시그널 번호도 출력합니다.서서 alarm_handler()
function, 「」, 「」입니다.SIGALRM
입니다만, 「」라고 하는 것은, 「」라고 하는 입니다.signal_handler()
도 SIGINT
★★★★★★★★★★★★★★★★★」SIGQUIT
동일한 기능이 두 가지 모두에 사용되므로 신호 번호로 사용합니다.
그런 다음 각 요소가 신호 번호와 해당 신호에 설치되는 핸들러를 식별하는 구조의 배열을 만듭니다.신호에 걱정하기로 3개의 신호에 대해 SIGHUP
,SIGPIPE
★★★★★★★★★★★★★★★★★」SIGTERM
정의되어 여부(정리되어 있는지 여부)에 대해서도 합니다.#ifdef
조건부 컴파일) 하지만 그것은 상황을 복잡하게 만들 뿐이다.POSIX POSIX도 수 것 .sigaction()
signal()
하지만 그것은 또 다른 문제입니다.처음부터 시작한 것을 계속합시다.
main()
기능하다핸들러에 , 「이러다」, 「이러다」를 호출합니다.signal()
현재 하려면 ,에 「」를 인스톨 합니다.SIG_IGN
핸들러로서 신호를 무시한 채로 유지합니다.되지 않았던 는, 「」를 호출해, 「 」 、 「 」signal()
핸들러를 값은 「」라고 생각됩니다). SIG_DFL
에 대한 첫 를 signal()로 입니다.SIG_IGN
★★★★★★★★★★★★★★★★★」signal()
값 「」을합니다( 「」).old
그 if
스테이트먼트는 다음과 같아야 합니다.SIG_IGN
할 수 - 이런 단언일 수 . - 이런 일 수 있습니다.SIG_ERR
뭔가 극적으로 잘못됐다면 - 하지만 나는 그 사실을 단언 발포로부터 배울 수 있을 것이다.)
그 후 프로그램은 정상적으로 종료됩니다.
함수의 이름은 적절한 유형의 함수에 대한 포인터로 간주할 수 있습니다.이니셜라이저 등 함수 호출 괄호를 적용하지 않으면 함수 이름이 함수 포인터가 됩니다.에 이 입니다.pointertofunction(arg1, arg2)
「」이 되는 ; 「」alarm_handler(1)
하면 될 것 같아요.alarm_handler
이며, 그 때문에, 「」는 「」입니다.alarm_handler(1)
는 함수 포인터를 통해 함수를 호출하는 것입니다.
것은 '아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아...SignalHandler
변수를 할당하는 올바른 유형의 값(두 개의 신호 핸들러 함수가 제공하는 값)이 있는 한 변수는 비교적 쉽게 사용할 수 있습니다.
이제 다시 두은 어떻게 할 보겠습니다. 어떻게 두 선언이signal()
로로관관관관
두 번째 선언을 검토하겠습니다.
extern SignalHandler signal(int signum, SignalHandler handler);
함수 이름과 유형을 다음과 같이 변경한 경우:
extern double function(int num1, double num2);
이 함수가 이 함수의 의미를 갖는다고 해석하는 데 문제가 없을 것입니다.int
a. a. a.double
double
value (그것이 문제라면 주저하지 않는 것이 좋을지도 모른다)
이제 ,, 이, 신, 신이 double
, . . . . . . . .signal()
에 ''가 .SignalHandler
두 번째 인수로, 결과로서 하나를 반환합니다.
이 메커니즘은 다음과 같이 취급할 수 있습니다.
extern void (*signal(int signum, void(*handler)(int signum)))(int signum);
설명하기가 까다롭기 때문에 아마 망칠 거예요이번에는 파라미터의 이름을 지정했습니다.이름은 중요하지 않습니다.
일반적으로 C에서 선언 메커니즘은 다음과 같이 기술합니다.
type var;
쓰면요.var
은 주어진 값을 .type
§:
int i; // i is an int
int *ip; // *ip is an int, so ip is a pointer to an integer
int abs(int val); // abs(-1) is an int, so abs is a (pointer to a)
// function returning an int and taking an int argument
준으 in in in 。typedef
클래스로 됩니다.static
★★★★★★★★★★★★★★★★★」extern
스토리지 클래스입니다.
typedef void (*SignalHandler)(int signum);
는 유형이 ㄴ, ㄴ, ㄴ, ㄴ, ㄴ, ㄴ, ㄴ, ㄴ, ㄴ, ㄴ, ㄴ, ㄴ, ㄴ, ㄴ, ㄴ, ㄴ, ㄴ, ㄴ)인SignalHandler
_ ) )는 다음과 같이
(*alarm_handler)(-1);
가 나타나다type void
가 없다 - 결과가 없다. - 결과가 없다. ★★★★★★★★★★★★★★★★★.(*alarm_handler)(-1);
의 호출입니다.alarm_handler()
를 -1
.
따라서 다음과 같이 선언합니다.
extern SignalHandler alt_signal(void);
그 의미는 다음과 같습니다.
(*alt_signal)();
void 값을 나타냅니다.그 때문에,
extern void (*alt_signal(void))(int signum);
,그러다,자,그러다,signal()
는 더 은 단순히 만 하는 이 아니기 때문입니다.SignalHandler
를 모두 할 수 있습니다.SignalHandler
★★★★
extern void (*signal(int signum, SignalHandler handler))(int signum);
extern void (*signal(int signum, void (*handler)(int signum)))(int signum);
그래도 혼란스럽다면, 어떻게 도와야 할지 잘 모르겠습니다.-아직은 알 수 없는 수준이지만, 저는 그것이 어떻게 작동하는지에 익숙해졌기 때문에 25년 정도 더 지속하면 그것이 당신에게 제2의 천성이 될 것이라고 말할 수 있습니다(그리고 당신이 똑똑하다면 조금 더 빨리 할 수도 있습니다).
함수 포인터는 다른 포인터와 같지만 데이터 주소 대신 함수의 주소를 가리킵니다(히프 또는 스택).다른 포인터와 마찬가지로 올바르게 입력해야 합니다.함수는 반환값 및 함수가 허용하는 파라미터 유형에 따라 정의됩니다.따라서 함수를 완전히 기술하려면 함수의 반환 값을 포함해야 하며 각 매개 변수의 유형이 허용됩니다.이러한 정의를 입력하면 해당 정의를 사용하여 포인터를 쉽게 만들고 참조할 수 있는 '친절한 이름'이 지정됩니다.
예를 들어 다음과 같은 함수가 있다고 가정합니다.
float doMultiplication (float num1, float num2 ) {
return num1 * num2; }
다음 typedef를 입력합니다.
typedef float(*pt2Func)(float, float);
위해 할 수 있다doMulitplication
a. 하는 함수에 대한 포인터를 각각 float .이는 단순히 플로트를 반환하고 각각 플로트 유형의 두 개의 파라미터를 취하는 함수에 대한 포인터를 정의하는 것입니다. 이름이 .pt2Func
해 주세요.pt2Func
플로트를 반환하고 2개의 플로트를 받는 모든 기능을 가리킬 수 있습니다.
따라서 다음과 같이 doMultiplication 기능을 가리키는 포인터를 만들 수 있습니다.
pt2Func *myFnPtr = &doMultiplication;
이 포인터를 사용하여 다음과 같이 함수를 호출할 수 있습니다.
float result = (*myFnPtr)(2.0, 5.1);
http://www.newty.de/fpt/index.html 를 참조해 주세요.
cdecl
는 함수 포인터 선언과 같은 이상한 구문을 해독하기 위한 훌륭한 도구입니다.또한 생성에도 사용할 수 있습니다.
을 (자신이나 다른 사람이) 향후 할 수 위한 라면, 는 '자신이나 사람이'를 만들 것을 합니다.typedef
작은 덩어리로 구성되며, 이러한 작은 조각을 크고 복잡한 표현에 대한 구성 요소로 사용합니다.예를 들어 다음과 같습니다.
typedef int (*FUNC_TYPE_1)(void);
typedef double (*FUNC_TYPE_2)(void);
typedef FUNC_TYPE_1 (*FUNC_TYPE_3)(FUNC_TYPE_2);
대신:
typedef int (*(*FUNC_TYPE_3)(double (*)(void)))(void);
cdecl
하다
cdecl> explain int (*FUNC_TYPE_1)(void)
declare FUNC_TYPE_1 as pointer to function (void) returning int
cdecl> explain double (*FUNC_TYPE_2)(void)
declare FUNC_TYPE_2 as pointer to function (void) returning double
cdecl> declare FUNC_TYPE_3 as pointer to function (pointer to function (void) returning double) returning pointer to function (void) returning int
int (*(*FUNC_TYPE_3)(double (*)(void )))(void )
그리고 (실제로) 내가 위에서 미친 듯이 난장판을 만든 것이 바로 그것이다.
함수 포인터의 typedef를 이해하는 매우 쉬운 방법:
int add(int a, int b)
{
return (a+b);
}
typedef int (*add_integer)(int, int); //declaration of function pointer
int main()
{
add_integer addition = add; //typedef assigns a new variable i.e. "addition" to original function "add"
int c = addition(11, 11); //calling function via new variable
printf("%d",c);
return 0;
}
int add(int a, int b)
{
return (a+b);
}
int minus(int a, int b)
{
return (a-b);
}
typedef int (*math_func)(int, int); //declaration of function pointer
int main()
{
math_func addition = add; //typedef assigns a new variable i.e. "addition" to original function "add"
math_func substract = minus; //typedef assigns a new variable i.e. "substract" to original function "minus"
int c = addition(11, 11); //calling function via new variable
printf("%d\n",c);
c = substract(11, 5); //calling function via new variable
printf("%d",c);
return 0;
}
이 출력은 다음과 같습니다.
22
6
두 함수의 선언에는 동일한 math_func 정의자가 사용되었습니다.
외부 구조에도 typedef의 동일한 접근방식을 사용할 수 있다.(다른 파일의 철골 구조 사용).
typedef
는 즉
C에서 스테이트 머신을 정의하는 예를 들어보겠습니다.
typedef int (*action_handler_t)(void *ctx, void *data);
, 그럼 이번에는 '어울리지 않다'라는 .action_handler
하여 2개의 포인터를 한다.int
상태 머신의 정의
typedef struct
{
state_t curr_state; /* Enum for the Current state */
event_t event; /* Enum for the event */
state_t next_state; /* Enum for the next state */
action_handler_t event_handler; /* Function-pointer to the action */
}state_element;
.typedef
주로 이 목적을 달성합니다.
모든 핸들러는 재음음음음음음음음음음음음음음음음음 defined defined defined defined defined defined defined defined defined defined에 정의된 .action_handler
int handle_event_a(void *fsm_ctx, void *in_msg );
int handle_event_b(void *fsm_ctx, void *in_msg );
참고 자료:
Linden의 Expert C 프로그래밍
이것은 제가 연습 삼아 작성한 함수 포인터와 함수 포인터 배열의 가장 간단한 예입니다.
typedef double (*pf)(double x); /*this defines a type pf */
double f1(double x) { return(x+x);}
double f2(double x) { return(x*x);}
pf pa[] = {f1, f2};
main()
{
pf p;
p = pa[0];
printf("%f\n", p(3.0));
p = pa[1];
printf("%f\n", p(3.0));
}
언급URL : https://stackoverflow.com/questions/1591361/understanding-typedefs-for-function-pointers-in-c
'itsource' 카테고리의 다른 글
gcc - O0은 여전히 "미사용" 코드를 최적화합니다.그것을 변경할 수 있는 컴파일 플래그가 있습니까? (0) | 2022.08.15 |
---|---|
Linux 플랫폼 드라이버와 일반 디바이스 드라이버의 차이점은 무엇입니까? (0) | 2022.08.15 |
스프링 부트:Embedded Servlet Container Factory 빈이 없어 Embedded Web Application Context를 시작할 수 없습니다. (0) | 2022.08.15 |
비동기 상태 변경 후 Vuex 기능 실행 (0) | 2022.08.15 |
열거형을 세트/목록으로 변환 (0) | 2022.08.15 |