zoukankan      html  css  js  c++  java
  • 常见复杂指针声明的解析(很详细)

    声明:1. 文章如有不妥的地方,请您指正,谢谢.
              2.另外文中有些细节可能引用您的内容却未给出参考,请原谅我的疏忽,你的共享我不会忘记.
              3. Email:lizhiguo0532@163.com  李枝果/lizgo
              4. 转载请保留该部分信息

    //两个原则
    //右左法则:首先从最里面的圆括号看起,然后往右看,再往左看。每当遇到圆括号时,就应该掉转阅读方向。一旦解析完圆括号里面所有的东西,就跳出圆括号。重复这个过程直到整个声明解析完毕。
    //坚持使用typedef来进行类型重定义,不确定优先级的地方可以多加括号。

    1. int *p[N];
    //这个就是int型指针数组,即N个int型指针所组成的数组
    2. int (*p)[N];
    //首先p是一个指针,基类型是具有N个int元素的数组,即数组指针
    3. int (*p[M])[N];或者int (*(p[M]))[N];
    //这是一个数组指针数组,怎么看呢?先看括号内的,*p[M],很显然这是一个数组(优先级[]高于*),什么数组呢?具有M个指针变量的数组。括号内的类型是指针,着我们知道了,跳出括号,int (指针)[N],
    //是不是很眼熟?看2的形式,所以里面的指针不是一般的指针,而是具有N个整型数据的数组指针。
    //如果现在我们要定义一个数组指针数组来访问二维数组a[5][4],该怎么定义呢?
    //我们就和解析的过程反着来定义就可以了,看到这个名字,“数组指针数组”,从左往右看,先看到数组指针,那我们就先来定义数组指针,注意,将来是要访问a[5][4]的(a是一个具有5个元素的数组,这5个元
    //素每个都是具有4个int数据的一维数组),将来我们的数组指针就是要指向这个一维数组的
    //数组指针定义:int (*p)[4];  再来定义指针数组,在这里前面的数据类型本来就已经是指针(数组指针)了,所以在 *pa[M]里就没必要加*了,可以直接定义成int (*p[M])[N];
    //如果我利用typedef就简单明了多了:
    //可以参考的形式有:
    //a.    
        typedef  int (*A)[N];
        typedef  A  (B[M]);

        B   b;//等价于int (*(b[M]))[N];比较局限
    //b.
        typedef  int (*A)[N];
        typedef  A  (B);

        B   b[M];//等价于int (*(b[M]))[N];
    //c.
        typedef  int      (A)[N];
        typedef  A    *(B[M]);

        B   b;//等价于int (*(b[M]))[N];比较局限
    //d.
        typedef  int      (A)[N];
        typedef  A      *(B);

        B   b[M];//等价于int (*(b[M]))[N];
    //e.
        typedef  int (*(A))[N];
        A   b[M];
    //f.
        typedef  int      A[N];
        A   *b[M];
    //上面的声明中,()在有的地方是可以不加的
    4. int (*func)(int *p);
    //这是一个基本的函数指针定义方法,无法分解。(这里说明的是:函数名内容也是地址)

    5. int (*func)(int *p, int (*f)(int*)); 
    //用typedef分解:
         typedef int (*FUNC)(int *);
         int (*func)(int *p,FUNC f);
    //典型的例子
         typedef void (*sighandler_t)(int);
         sighandler_t signal(int signum, sighandler_t handler);
    //展开如下:
        void     (* signal(int signum, void (* handler)(int)))(int );

    6. int (*func[5])(int *p);
    // 这是一个函数指针数组,总的来说func是个数组,什么样的数组呢?原来里面的数组元素都是一个个函数指针。可以这样分解
         typedef int (* FUNC)(int *p);
         FUNC   func[5];
    //func这个数组的元素的类型是参数维int *,返回值为int 的函数指针

    7. int (*(*func)[5])(int *p);
    //这是一个函数指针数组指针,注意读法,前面六个字函数指针数组是修饰最后的指针,所以总提来说func是一个指针,什么样的指针呢?
    //指向具有5个元素的数组,那这个数组的元素是什么类型呢?哦,原来是函数指针类型,什么类型的函数指针呢?参数int *,返回值 int。
    //用typedef分解
        typedef int (* (A))(int *p);
        typedef A   (B)[5];
        typedef B    *M
        M    func;
        //或者
        B   *func;

    8. int (*(*func)(int *p))[5]; 
    //乍一看,我也看不出来它什么类型,不过可以分解嘛
        typedef  int (*(A))[5];//A是函数指针类型
        A  (* func)(int *p);
        //这下该看出来是什么类型来吧,func是个函数指针,它参数很简单 int *,复杂就复杂在返回值,返回值的类型是A,A的类型就是一个数组指针,
        //而且这个数组指针指向的是具有5个int数据的数组。


    总结:
    1.如果我们是去读别人的已经声明好的复杂类型,那么我们可以这样,用typedef来将其分解,分解的原则是:
        从最外层的开始用typedef来定义,然后用定义好的类型再去一层一层得定义内部,知道遇见了被定义的标示符为止
    2.如果我们知道需要声明一个什么东西了,比如前面的 “函数指针数组指针”,我们这样来声明:从左往右看,找到第一个修饰词“函数指针”,我们就定义一个函数指针
        接下来遇到来“数组”,我们再用定义好的函数指针类型来定义一个数组。最后,我们在这个数组的类型上再定义一个指针就 可以了。

  • 相关阅读:
    Linux内核配置过程
    Linux内核最顶层文档
    LeetCode 11月第2周题目汇总
    Chapter0
    序列加法的讨论
    ch2-基本工具介绍
    ch1-数据科学概述
    在Linux下制作Linux&windows启动盘
    VMware Workstation 与 Device/Credential Guard 不兼容?
    Linux mint 19.3配置CUDA+安装Tensorflow
  • 原文地址:https://www.cnblogs.com/coolYuan/p/9084705.html
Copyright © 2011-2022 走看看