代码之家  ›  专栏  ›  技术社区  ›  nmuntz

C中混合的指针、数组和函数类型声明

c
  •  8
  • nmuntz  · 技术社区  · 15 年前

    我的一个朋友在C上测试我(我最强的语言是C++),他问了我三个我无法回答的问题:

    尝试解释以下声明:

    1) int (*x)(int, char *, void *);
    2) int (*x[10])(int, char *, void *);
    3) int (**x[10])(int, char *, void *);
    

    有人能解释这些函数声明并解释正在使用的概念吗?

    5 回复  |  直到 13 年前
        1
  •  21
  •   Johannes Schaub - litb    15 年前

    第一个是指向函数的指针。换句话说,它声明一个变量“x”,该变量指向以下类型的函数:

    int function(int, char*, void*);
    

    其用途如下:

    int myfunc(int a, char* b, void* c) {
        return a;
    }
    
    void acallingfunction() {
        int (*x)(int, char*, void*);
        x = myfunc;
        x(1, "hello", 0);
    }
    

    第二个似乎是无效的语法,但我可能错了。如果它在x之前有一个星号(例如int(*x[10])(int,char*,void*),它将是一个函数指针数组,并将像普通数组一样使用:

    x[3](1, "Hi there", 0);
    

    第三个是指向函数指针的指针数组,这似乎不实际,但完全有效。示例用法可能是:

    void anothercaller() {
        int (*x)(int, char*, void*);
        int (**y)(int, char*, void*);
        x = myfunc;
        y = &x;
        (*y)(1, "hello", 0);
    }
    

    注意,前两个比较常见。指向函数的指针用于在C中完成回调和各种面向对象的编程概念。指向函数的指针数组可用于事件表,以查找适当的回调。

    请注意,所有这些实际上都是有效的C++。;)

    编辑:我显然犯了void main()的暴行。

    编辑2:正如ChrisLutz在下面指出的,它们确实应该用typedef包装。typedef使包含指向函数的指针的代码更加清晰。

        2
  •  31
  •   hlovdal    15 年前

    你需要 cdecl 程序,它将给你一个明确的,正确的回答这些问题。学会手工解释这些陈述是可行和有益的,但是即使如此,CDECL对于检查您是否有正确的答案也是非常有用的。

    prompt>cdecl
    Type `help' or `?' for help
    cdecl> explain int (*x)(int, char *, void *);
    declare x as pointer to function (int, pointer to char, pointer to void) returning int
    cdecl> explain int (*x[10])(int, char *, void *);
    declare x as array 10 of pointer to function (int, pointer to char, pointer to void) returning int
    cdecl> explain int (**x[10])(int, char *, void *);
    declare x as array 10 of pointer to pointer to function (int, pointer to char, pointer to void) returning int
    cdecl>
    
        3
  •  7
  •   tensaix2j    15 年前
    1. 函数指针
    2. 函数指针数组
    3. 指向函数指针的指针数组
        4
  •  6
  •   Community Romance    7 年前

    它们是函数指针,如上所述,但写得相当令人讨厌(在我看来)。我写它们的方式是:

    typedef int (*funcptr)(int, char *, void *);
    
    funcptr x;
    funcptr x[10];
    funcptr *x;
    

    Walt W's excellent answer 有关函数指针的详细信息。

        5
  •  3
  •   Johannes Schaub - litb    15 年前

    因为C的语法就像C++中的一个, geordi 可能对你有意思。它是教和学习这些声明的另一个很好的工具(以及其他与C++相关的东西,有时也是C)。

    geordi: << ETYPE_DESC(x); int (*x)(int, char *, void *);
    lvalue pointer to a function taking an integer, a pointer to a character, a pointer to anything, and returning an integer
    
    geordi: << ETYPE_DESC(x); int (*x[10])(int, char *, void *);
    lvalue array of 10 pointers to functions taking an integer, a pointer to a character, a pointer to anything, and returning integers
    
    geordi: << ETYPE_DESC(x); int (**x[10])(int, char *, void *);
    lvalue array of 10 pointers to pointers to functions taking an integer, a pointer to a character, a pointer to anything, and returning integers
    

    正如它的页面所解释的,它可以做得更多,包括为您构建一个类型。

    geordi: make type array of 10 pointers to functions taking an integer and returning void
    void(*[10])(int)
    

    如果您原则上知道如何申报物品,但不确定只有一件物品,您可以使用括号:

    geordi: make type ( void(int, bool) )*
    void(*)(int, bool)
    

    如果您想了解标识符的情况,也可以更改名称的类型。

    geordi: -c int x;
    Success
    geordi: make x a ( void(int, bool) )* and show
    -c void (* x)(int, bool) ;
    

    如果您构建了一个声明,但不确定运算符的优先级,那么geordi的优先级函数可以帮助您解决这个问题。

    geordi: precedence *x(a, b)
    *(x(a, b))