programing

이 코드의 의미는 무엇입니까?void(*int sig, void(*func)(int))(int);

minimums 2023. 7. 22. 09:53
반응형

이 코드의 의미는 무엇입니까?void(*int sig, void(*func)(int))(int);

저는 이 코드를 우연히 발견했고 그것의 의미를 해석하는 것을 완전히 잃어버렸습니다.

#include <signal.h>
void (*signal(int sig, void (*func)(int)))(int);

2호선 코드에 대한 자세한 설명은 무엇입니까?

나는 그것을 알고 있습니다.void그리고.int*func는 함수의 포인터이며 괄호는 우선 순위를 나타냅니다.하지만 (*signal...), (int), 그리고 전체가 함께 결합된 것은 여전히 이해할 수 없습니다.세부적일수록 좋습니다.

아마도 나는 이 선언의 의미/효과를 알고 있었을 것입니다.하지만 저는 아래와 같이 무슨 일이 일어나고 있는지 이해하기 위해 몇 가지 더 실험을 해야 했습니다.

  1 #include <signal.h>
  2 void (*signal)(int sig, void (*func)(int));
  3 void (*signal)(int);  // then void (signal)(int) again.
  4 //void (*signal(int sig, void (*func)(int)))(int); //break this line into two lines above
  5
  6 int main(){}

위의 코드에서, 나는 부러졌습니다.void (*signal(int sig, void (*func)(int)))(int)두 줄로3번 라인은 둘 다 시도했습니다.void (*signal)(int)그리고.void (signal)(int)내가 다시 신고하려고 했던 것과 같은 오류 결과로signal:

TestDeclaration.c:2: 'signal' 이의류로 /usr/include/signal 다시언h:: '이전 :93: 이: 'filename'이었습니다.
TestDeclaration.c:3: 'signal' 이의류로 /usr/include/signal 다시언.: '이전 :93: 이: 'filename'이었습니다.

이제 저는 두 재판이 잘못된 선언 방법이라는 것을 알지만, 왜 그것들이 잘못된 것일까요?왜 원래의 선언 방식은 재선언이 아닌가요?

▁an▁를 취하는 함수의 int함수에 대한 그고함찍포대터인한에수기(리찍())int 및 를 가져옴)int그리고 무효가 반환됩니다.


설명 또는 해석 가이드

괄호 안의 모든 항목을 단일 엔터티로 처리한 다음 "선언은 사용법을 따릅니다" 규칙을 사용하여 내부 작업을 수행하여 해석할 수 있습니다.

무효의
  (*sig(int sig, void(*func)(int)) (int);

는 괄호안엔다음같은함수사보것입다처니럼용는하를과는티를 취하는 .int그리고 돌아오는void.

외부 부품 제거:

*signal(int sig, void (*func)(int))

그렇게,signal는 일부 변수를 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " 을 합니다.*)를 취하여 int그리고 돌아오는void.

이것은 의미합니다.signal이 함수를 사용하는 경우).int그리고 돌아오는void).

필요한 매개변수를 보면,int (계속,sig및 ) 및void (*func)(int)입니다.int그리고 돌아오는void).

이것은 C 선언이 어떻게 복잡해질 수 있는지에 대한 고전적인 예 중 하나입니다.
이 선언을 이해하려면 일반적으로 typeef를 소개하는 데 도움이 됩니다.

typedef void (*sighandler_t)(int);
sighandler_t signal(int sig, sighandler_t func);

typedef는 함수에 대한 포인터를 선언합니다(int 매개 변수를 사용하고 아무것도 반환하지 않음).signal이제 두 개의 매개 변수(함수에 대한 int와 포인터)를 취하고 함수에 대한 포인터를 반환하는 함수로 볼 수 있습니다.

이것은 또한 원래 선언에서 파생될 수 있지만, 약간의 연습이 필요합니다.은 가장 엔티티의 을 짓는 입니다.signal 예를 들어옴):

signal ...의 문제야...

이 맞지 을 찾을 : 그런다음일치지괄또선는끝다읽찾습니오때른을쪽까지을을의언호는하는닫않▁then다▁right니습읽▁untilis▁or▁read▁you▁the을른ation:오▁you▁parenthes▁declar쪽▁an까▁end런그▁closing▁the▁of지▁unmatched때을.void (*signal(int sig, void (*func)(int))(int)

signal을 반환하는 입니다.

이제 매개 변수를 먼저 구문 분석하거나 반환 값을 먼저 구문 분석할 수 있습니다.제가 먼저 반품 금액을 알려드리겠습니다.위해, 괄호를 : 이를위다음같이뒤로읽일열찾다괄습니호를린는하치.void (signal( / ... */ ))(int)

signal...에반환하는 함수입니다.

이런 식으로 앞뒤로 읽으면 다음과 같은 단계를 거치게 됩니다.

signal로 포인터를 입니다. (... ...로 포인터를 반환하는 함수입니다(... 반환하는 함수).

signal포인터를 ...로 반환하는 함수입니다(공백을 ...로 반환하는 함수).

signal포인터를 ...로 반환하는 함수입니다(함수가 int를 가져가고 void를 반환함).

signal는 (void를 의 두 변수를 ( void를 int)로 합니다.

내가 수년 전에 만든 니모닉은 복잡한 유형을 이해하려고 할 때 매우 유용합니다.

Remember these rules for C declares
And precedence never will be in doubt
Start with the Suffix, Proceed with the Prefix
And read both sets from the inside, out.

물론 괄호가 그 우선순위를 변경하는 경우는 제외합니다.

이 경우에 적용:

void (*signal(int sig, void (*func)(int)))(int);

signal is:
  [inside parentheses]
  [suffix ()] a function, whose arguments are
    sig, which is [prefix int] an integer, and
      func, which is:
         [inside parentheses]
           [no suffix within these parens]
           [prefix *] a pointer to
         [suffix ()] a function, whose argument is
           an int
         [no more suffixes]
         [prefix void] and which returns void
         [no more prefixes]
       [no more arguments]
     [prefix *] And which returns a pointer to
     [no more prefixes within these parens]
   [suffix ()] a function, whose argument is
      an int
   [no more suffixes]
   [prefix void] and which returns void.

조금만 연습하면 모든 작업을 즉시 수행할 수 있습니다.

"Signal is function, whose arguments are:
    sig, an integer,
    and func, a pointer to a function whose argument is an int and which returns void
... which returns a pointer to a function that takes int as an argument and returns void.

(처음 오류가 발생해서 죄송합니다. 제가 연습이 부족합니다.)

예, 그 니모닉("물론 괄호 제외"라는 암시가 있는)은 포인터, 배열 및 함수가 아무리 잘못 혼합되어 있더라도 모든 C 선언에 대해 작동합니다.

이것은 다른 사람의 코드가 어떻게 작동하는지 알아내려고 할 때 정말 유용한 기술입니다.오랫동안 보지 못했던 자신만의 것을 찾아내기도 합니다.

하지만, 네, 사람들이 한 눈에 읽을 수 없을 것이라고 생각하는 것을 다루는 더 나은 방법은 그것을 타이프로 겹겹이 쌓아 올리는 것입니다.구성 요소 유형 자체가 유용할 수 있으며, 한 번에 한 단계씩 수행하면 어떤 괄호가 어떤 괄호와 일치하는지 파악하는 데 어려움을 겪지 않습니다.당신의 코드를 만지는 다음 사람에게 친절하게 대하세요!

니모닉이 유용하다고 생각되면, 다른 곳에서 자유롭게 인용하세요. 그냥 저자로서 저를 믿어주세요.

참고로, C delaractions를 구문 분석하고 영어 설명으로 변환하는 "C Descriptor" 도구도 있습니다.제 것은 CEX라고 불렸습니다. 명백한 이유 때문이죠. 하지만 다른 것들도 많이 존재합니다. 만약 여러분이 이 기술을 웨트웨어에 적용하고 싶지 않거나 누군가 여러분이 추적하기에는 너무 추악한 것을 여러분에게 건네준다면, 여러분은 CEX를 찾을 수 있을 것입니다.

이 불쾌한 선언이 어떻게 사용될 수 있는지 예를 들어 보겠습니다.

void (*signal(int sig, void (*func)(int)))(int);

너무 상세하지 않은 "신호"는 함수를 반환하는 두 가지 매개 변수를 가진 함수라고 할 수 있습니다.

#include <stdio.h>

// First function that could be returned by our principal function
// Note that we can point to it using void (*f)(int)
void car_is_red(int color)
{
    printf("[car_is_red] Color %d (red) is my favorite color too !\n", color);
}

// Second function that could be returned by our principal function
// Note that we can point to it using void (*f)(int)
void car_is_gray(int color)
{
    printf("[car_is_gray] I don't like the color %d (gray) either !\n", color);
}

// The function taken as second parameter by our principal function
// Note that we can point to it using void (*func)(int)
void show_car_type(int mod)
{
    printf("[show_car_type] Our car has the type: %d\n",mod);
}

/* Our principal function. Takes two parameters, returns a function. */
void (* show_car_attributes(int color, void (*func)(int)) )(int)
{
    printf("[show_car_attributes] Our car has the color: %d\n",color); // Use the first parameter

    int mod = 11;  // Some local variable of our function show_car_attributes()
    func(mod);  // Call the function pointed by the second parameter (i.e. show_car_type() )

    // Depending on color value, return the pointer to one of two functions
    // Note that we do NOT use braces with function names
    if (color == 1)
        return car_is_red;
    else
        return car_is_gray;
    }


//main() function
int main()
{
    int color = 2;   // Declare our color for the car
    void (*f)(int);  // Declare a pointer to a function with one parameter (int)

    f = show_car_attributes(color, show_car_type); // f will take the return 
           // value of our principal function. Stated without braces, the 
           // parameter  "show_car_types" is a function pointer of type 
           // void (*func)(int).

    f(color);  // Call function that was returned by show_car_attributes()

    return 0;
}

출력 내용을 살펴보겠습니다.

색상 = 1인 경우

[show_car_attributes] Our car has the color: 1
[show_car_type] Our car has the type: 11
[car_is_red] Color 1 (red) is my favorite color too !

색상 = 2인 경우

[show_car_attributes] Our car has the color: 2
[show_car_type] Our car has the type: 11
[car_is_gray] I don't like the color 2 (gray) either !

다음을 수행하는 함수로 포인터 반환:

  • 정수를 첫 번째 인수로 지정하고
  • 함수에 대한 포인터(int를 가져다가 void를 반환함)를 두 번째 인수로 사용합니다.

정수 인수를 사용합니다.

언급URL : https://stackoverflow.com/questions/3706704/whats-the-meaning-of-this-piece-of-code-void-signalint-sig-void-funcin

반응형