C指针复杂声明

游梦惊园
  • 1.1k
char (*(*x())[])();

char (*(*x[3])())[5];

请描述一下上面的两个指针的含义,如果能写两个实例的话,就更好了。

回复
阅读 2.6k
5 个回答
✓ 已被采纳

对于这种复杂的声明格式,可以采用替换的形式来看明白。

比如char (*(*x())[])();这个, 你可以找个 a代替括号里面的,然后逐步代替。

char (*(*x())[])();
// 用a 代替 (*x())[]
char (*a)();
// 上面的a的意思就是一个函数指针,空参,返回char
// 再看(*x())[],用b代替 *x()
(b)[];
// b是一个数组,而且数组每一项是一个指针a
*x();
// x是一个空参函数,返回类型是一个b的指针

所以上面的x是一个函数,参数为空,返回值是一个数组的指针,数组的每一项是一个指针,指向的是一个函数指针,这个函数的形式是空参返回char。

所以使用的方式就是

char f1(){return 1;};
char f2(){return 2;};

char (*(*x())[2])(){
    typedef char A();
    
    A* f = f1;
    
    typedef A* B[];
    
    B arr = {f,f};
    
    typedef B* F();
    
    return &arr;    
};

同样的道理
char (*(*x[3])())[5];这个表达式的使用方式就是

typedef char A[5];

A* b(){
    static A a = {1,2,3,4,5};
    return &a;
}

typedef A* B();

char (*(*x[3])())[5] = {&b,&b,&b};

也就是说x 是个有3个值的数组,每个数组的类型是一个函数指针,这个函数(b)是空参,返回的是一个指针,指向一个含有5个char的数组。

关于C语言声明问题。任何不介绍 http://cdecl.org/ 的答案都是耍流氓。
这原本其实是一个unix程序(或其他系统),被改造成了在线版。
通过这个网站,你可以检查自己的答案是否正确。

建议根据优先级来推论,不建议用替换法,因为替换的元素不同可能会导致优先级与原来的声明不同。
所以我建议参考 bbaimu 的答案。李引证的答案中有一个表达的小错误,他在表达第一题数组元素时
用了两次指针,这是不对的。正确的表述应该是 数组的每一个元素是一个函数指针

另外,建议参考书籍《C和指针》中高级指针那章,
还有《C Programming: A Modern Approach》 - K. N. King 关于声明详细介绍那章

char (*(*x())[])();

char (* (*x()) [])();
// 首先()优先级大于*,x是一个函数
// 函数 x 的返回值是一个指向某种类型的指针,类型是fun
char ( *fun[] )();
// [] 优先级大于 *
// fun的类型是数组,数组的每一个元素是一个函数指针
// 函数的类型
char f();

实例:
char fun()
{
    return 1;
}

char (*(*x())[2])() 
{
    char fun();
    char (*array[2])()= {&fun, &fun};
    return  &array;
}
char (*(*x[3])())[5];

char (*(  *x[3]  )())[5];
//首先[] 优先级大于 *
// x 是一个数值,数组的长度为3,数组的每个元素是一个指针
// 指针指向的类型是fun
char ( * fun () )[5];
//fun是一个函数,函数的返回值是一个指针
//指针的类型是 f,f的类型是一个char类型的数组
char f[5];

实例:
    char (*fun())[5];
    char (*(*x[3])())[5] = {&fun, &fun, &fun};

    char (*fun())[5]
    {
        char array[5];
        return &array;
    }

能写出这种代码的人,对于后期代码维护简直就是个灾难。如果这个人走了

1、x是一个函数,这个函数不接受参数,并返回指针,指针指向数组,数组的元素是函数指针,函数指针指向的函数不接受参数,并返回char

2、x是一个数组,数组包含3个函数指针,函数指针指向的函数不接受参数,并返回指针指向包含5个char元素的数组

#include <stdio.h>

typedef char (*(*baz())[])();
typedef char (*(*foo[3])())[5];
typedef char (*bar)[5];
typedef char (*(*far)[])();
typedef char (*faz)();

char boo() {};


far func1()
{
    faz array[] = {&boo, &boo};
    /*注意:这是错误做法,只是为了例子需要*/
    return &array;
}

bar func2()
{
    char array[5] = {1, 2, 3, 4, 5};
    /*注意:这是错误做法,只是为了例子需要*/
    return &array;
}


int main(int argc, const char* argv[])
{
    foo foo = {&func2, &func2, &func2};

    return 0;
}
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
你知道吗?

宣传栏