What's the meaning of this piece of code? void (*signal(int sig, void (*func)(int)))(int);

后端 未结 5 1830
眼角桃花
眼角桃花 2020-11-27 14:45

I came across this piece of code and completely got lost interpreting its meaning.

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


        
5条回答
  •  盖世英雄少女心
    2020-11-27 15:44

    A mnemonic I created many years ago, which is invaluable when trying to understand complicated types:

    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.
    

    Except where parentheses change that precedence, of course.

    Applying it to this case:

    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.
    

    With a bit of practice, you'll get to the point where you can do all that on the fly:

    "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.
    

    (Sorry about the error first time out -- I'm out of practice.)

    Yes, that mnemonic (with the implied "except for parentheses, of course) works for all C declarations, no matter how badly the pointers, arrays, and functions are intermixed.

    This is a REALLY useful skill to have when trying to figure out how someone else's code works... or even figuring out something of your own that you haven't seen in a long time.

    But, yes, the better way to handle anything that you don't think people will be able to read at a glance is to build it up in layers with typedefs. The component types are likely to be useful themselves, and taking it one step at a time keeps people from getting lost trying to figure out which parenthesis matches which. Be kind to the next person who touches your code!

    If you find the mnemonic useful, feel free to quote it elsewhere -- just give me credit as its author, please.

    By the way, there are also "C Explainer" tools which will parse C delaractions and do the conversion to English description for you. Mine was called CEX, for obvious reasons, but many others exist and you should be able to find one if you don't want to commit this skill to wetware or if someone hands you something that's really too ugly for you to keep track of.

提交回复
热议问题