C 复杂数据类型的typedef

C 复杂数据类型的typedef,c,pointers,types,C,Pointers,Types,我试图从语法的角度理解C如何处理复杂类型定义的基本机制 考虑以下示例(问题末尾包含参考资料) 是正确的声明,即p1d这里是指向 10个整数,与使用数组类型的声明下相同。 请注意,这与 typedef int *p1d[10]; 这将使p1d成为一个包含10个指向int类型指针的数组的名称 这样,如果我考虑两个例子中的运算符优先级(我将重写它们): 所以,从左到右读取,并使用运算符优先级,我得到:“指向int类型的指针,命名为p1d,大小为10”,这是错误的。至于另一个/第一个案例: int (

我试图从语法的角度理解C如何处理复杂类型定义的基本机制

考虑以下示例(问题末尾包含参考资料)

是正确的声明,即p1d这里是指向 10个整数,与使用数组类型的声明下相同。 请注意,这与

typedef int *p1d[10];
这将使p1d成为一个包含10个指向int类型指针的数组的名称

这样,如果我考虑两个例子中的运算符优先级(我将重写它们):

所以,从左到右读取,并使用运算符优先级,我得到:“指向int类型的指针,命名为p1d,大小为10”,这是错误的。至于另一个/第一个案例:

int (*p1d)[10];
我读作“p1d是一个指针,int类型,是一个由10个这样的元素组成的数组”,这也是错误的

有人能解释一下用于确定这些类型定义的规则吗?我也想将它们应用于函数指针,我希望本次讨论也能解释
const
cast(即:指向常量数据的指针与指向变量数据的常量指针)背后的逻辑

多谢各位

参考文献:


  • C教程:指向数组的指针:
  • 运算符优先级:

  • 我的一位教授写道。读一读,这是值得的,希望能回答任何问题

    所有功劳都归于瑞克·奥德()


    将科帕尼霍勒的规则简化一点,可以归结为:

  • 找到最左边的标识符
  • 解决方法是,记住没有通过括号显式分组,函数调用
    ()
    []
    *
    之前绑定
  • 递归地应用于任何函数参数
  • 因此,
    T*a[]
    是指针数组tp
    T
    T(*a)[/code>是指针数组
    T
    T*f()
    是指针返回
    T
    ,而
    T(*f)(
    是指针返回
    T

    举一个让很多人心痛的例子,我们可以看看POSIX
    signal
    函数的原型:

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

           signal                                          -- signal
           signal(                             )           -- is a function with
           signal(     sig                     )           -- parameter sig
           signal( int sig                     )           --   of type int
           signal( int sig,        func        )           -- and parameter func
           signal( int sig,      (*func)       )           --   of type pointer to
           signal( int sig,      (*func)(     ))           --   a function with
           signal( int sig,      (*func)( int ))           --     an int parameter
           signal( int sig, void (*func)( int ))           --   returning void
         (*signal( int sig, void (*func)( int )))          -- returning a pointer to
         (*signal( int sig, void (*func)( int )))(     )   --   a function with
         (*signal( int sig, void (*func)( int )))( int )   --     an int parameter
    void (*signal( int sig, void (*func)( int )))( int )   --   returning void
    

    运算符优先级与任何事情都无关。你的代码中没有运算符。如果你不使用
    typedef
    ,这是一个
    typedef
    ?修复了我文章中的打字错误。另一个有用的链接。到目前为止,可能重复的链接已经被证明是有用的。你有没有办法把它贴到你的答案里,这样就可以保留一份副本了?看来你帮我处理好了:嗯,这是一个非常好的答案,我一直在寻找这样一个好例子。如果链接断了,失去它将是一种耻辱。谢谢@KepaniHaole:解读复杂声明的优秀指南。谢谢你的发帖。
    The "right-left" rule is a completely regular rule for deciphering C
    declarations.  It can also be useful in creating them.
    
    First, symbols.  Read
    
         *      as "pointer to"         - always on the left side
         []     as "array of"           - always on the right side
         ()     as "function returning"     - always on the right side
    
    as you encounter them in the declaration.
    
    STEP 1
    ------
    Find the identifier.  This is your starting point.  Then say to yourself,
    "identifier is."  You've started your declaration.
    
    STEP 2
    ------
    Look at the symbols on the right of the identifier.  If, say, you find "()"
    there, then you know that this is the declaration for a function.  So you
    would then have "identifier is function returning".  Or if you found a 
    "[]" there, you would say "identifier is array of".  Continue right until
    you run out of symbols *OR* hit a *right* parenthesis ")".  (If you hit a 
    left parenthesis, that's the beginning of a () symbol, even if there
    is stuff in between the parentheses.  More on that below.)
    
    STEP 3
    ------
    Look at the symbols to the left of the identifier.  If it is not one of our
    symbols above (say, something like "int"), just say it.  Otherwise, translate
    it into English using that table above.  Keep going left until you run out of
    symbols *OR* hit a *left* parenthesis "(".  
    
    Now repeat steps 2 and 3 until you've formed your declaration.  Here are some
    examples:
    
         int *p[];
    
    1) Find identifier.          int *p[];
                                      ^
       "p is"
    
    2) Move right until out of symbols or right parenthesis hit.
                                 int *p[];
                                       ^^
       "p is array of"
    
    3) Can't move right anymore (out of symbols), so move left and find:
                                 int *p[];
                                     ^
       "p is array of pointer to"
    
    4) Keep going left and find:
                                 int *p[];
                                 ^^^
       "p is array of pointer to int". 
       (or "p is an array where each element is of type pointer to int")
    
    Another example:
    
       int *(*func())();
    
    1) Find the identifier.      int *(*func())();
                                        ^^^^
       "func is"
    
    2) Move right.               int *(*func())();
                                            ^^
       "func is function returning"
    
    3) Can't move right anymore because of the right parenthesis, so move left.
                                 int *(*func())();
                                       ^
       "func is function returning pointer to"
    
    4) Can't move left anymore because of the left parenthesis, so keep going
       right.                    int *(*func())();
                                               ^^
       "func is function returning pointer to function returning"
    
    5) Can't move right anymore because we're out of symbols, so go left.
                                 int *(*func())();
                                     ^
       "func is function returning pointer to function returning pointer to"
    
    6) And finally, keep going left, because there's nothing left on the right.
                                 int *(*func())();
                                 ^^^
       "func is function returning pointer to function returning pointer to int".
    
    
    As you can see, this rule can be quite useful.  You can also use it to
    sanity check yourself while you are creating declarations, and to give
    you a hint about where to put the next symbol and whether parentheses
    are required.
    
    Some declarations look much more complicated than they are due to array
    sizes and argument lists in prototype form.  If you see "[3]", that's
    read as "array (size 3) of...".  If you see "(char *,int)" that's read
    as "function expecting (char *,int) and returning...".  Here's a fun
    one:
    
                     int (*(*fun_one)(char *,double))[9][20];
    
    I won't go through each of the steps to decipher this one.
    
    Ok.  It's:
    
         "fun_one is pointer to function expecting (char *,double) and 
          returning pointer to array (size 9) of array (size 20) of int."
    
    As you can see, it's not as complicated if you get rid of the array sizes
    and argument lists:
    
         int (*(*fun_one)())[][];
    
    You can decipher it that way, and then put in the array sizes and argument
    lists later.
    
    Some final words:
    
    It is quite possible to make illegal declarations using this rule,
    so some knowledge of what's legal in C is necessary.  For instance,
    if the above had been:
    
         int *((*fun_one)())[][];
    
    it would have been "fun_one is pointer to function returning array of array of
                                              ^^^^^^^^^^^^^^^^^^^^^^^^
    pointer to int".  Since a function cannot return an array, but only a 
    pointer to an array, that declaration is illegal.
    
    
    Illegal combinations include:
    
         []() - cannot have an array of functions
         ()() - cannot have a function that returns a function
         ()[] - cannot have a function that returns an array
    
    In all the above cases, you would need a set of parens to bind a *
    symbol on the left between these () and [] right-side symbols in order
    for the declaration to be legal.
    
    Here are some legal and illegal examples:
    
    int i;                  an int
    int *p;                 an int pointer (ptr to an int)
    int a[];                an array of ints
    int f();                a function returning an int
    int **pp;               a pointer to an int pointer (ptr to a ptr to an int)
    int (*pa)[];            a pointer to an array of ints
    int (*pf)();            a pointer to a function returning an int
    int *ap[];              an array of int pointers (array of ptrs to ints)
    int aa[][];             an array of arrays of ints
    int af[]();             an array of functions returning an int (ILLEGAL)
    int *fp();              a function returning an int pointer
    int fa()[];             a function returning an array of ints (ILLEGAL)
    int ff()();             a function returning a function returning an int
                                    (ILLEGAL)
    int ***ppp;             a pointer to a pointer to an int pointer
    int (**ppa)[];          a pointer to a pointer to an array of ints
    int (**ppf)();          a pointer to a pointer to a function returning an int
    int *(*pap)[];          a pointer to an array of int pointers
    int (*paa)[][];         a pointer to an array of arrays of ints
    int (*paf)[]();         a pointer to a an array of functions returning an int
                                    (ILLEGAL)
    int *(*pfp)();          a pointer to a function returning an int pointer
    int (*pfa)()[];         a pointer to a function returning an array of ints
                                    (ILLEGAL)
    int (*pff)()();         a pointer to a function returning a function
                                    returning an int (ILLEGAL)
    int **app[];            an array of pointers to int pointers
    int (*apa[])[];         an array of pointers to arrays of ints
    int (*apf[])();         an array of pointers to functions returning an int
    int *aap[][];           an array of arrays of int pointers
    int aaa[][][];          an array of arrays of arrays of ints
    int aaf[][]();          an array of arrays of functions returning an int
                                    (ILLEGAL)
    int *afp[]();           an array of functions returning int pointers (ILLEGAL)
    int afa[]()[];          an array of functions returning an array of ints
                                    (ILLEGAL)
    int aff[]()();          an array of functions returning functions
                                    returning an int (ILLEGAL)
    int **fpp();            a function returning a pointer to an int pointer
    int (*fpa())[];         a function returning a pointer to an array of ints
    int (*fpf())();         a function returning a pointer to a function
                                    returning an int
    int *fap()[];           a function returning an array of int pointers (ILLEGAL)
    int faa()[][];          a function returning an array of arrays of ints
                                    (ILLEGAL)
    int faf()[]();          a function returning an array of functions
                                    returning an int (ILLEGAL)
    int *ffp()();           a function returning a function
                                    returning an int pointer (ILLEGAL)
    
    void (*signal( int sig, void (*func)( int )))( int );
    
           signal                                          -- signal
           signal(                             )           -- is a function with
           signal(     sig                     )           -- parameter sig
           signal( int sig                     )           --   of type int
           signal( int sig,        func        )           -- and parameter func
           signal( int sig,      (*func)       )           --   of type pointer to
           signal( int sig,      (*func)(     ))           --   a function with
           signal( int sig,      (*func)( int ))           --     an int parameter
           signal( int sig, void (*func)( int ))           --   returning void
         (*signal( int sig, void (*func)( int )))          -- returning a pointer to
         (*signal( int sig, void (*func)( int )))(     )   --   a function with
         (*signal( int sig, void (*func)( int )))( int )   --     an int parameter
    void (*signal( int sig, void (*func)( int )))( int )   --   returning void