zoukankan      html  css  js  c++  java
  • 彻底了解指针数组,数组指针以及函数指针

    应用自:http://bbs.chinaunix.net/thread-377291-1-1.html

    小弟是一个软件工程师,做unix c/c++ java的开发,每次碰到问题都跑到CU里问人,呵呵,昨天在碰到一个指针数组的问题的时候,由于好久没用,感觉有些陌生了,所以今天归纳总结了一下,希望以后的朋友可以少走些弯路,也不知道对大家有没有用处:)
    一 :关于指针和堆的内存分配
    (1) 指针数组 : 一个数组里放的都是指针,我们把他叫做指针数组:)
    int * a[10]; 由于它是一个数组,他是不能从堆空间里申请空间的。
    只能做个循环,每个元素去申请空间,或者每个元素去指向另外的地址空间。     
    ( 2 ) 数组指针 : 一个指向一唯或者多唯数组的指针;
    int * b=new int[10]; 指向一唯数组的指针b ;
    a 指向了一个栈空间中10个并排放置的 int 型元素的首地址
    int (*b2)[10]=new int[10][10]; 注意,这里的b2指向了一个二唯int型数组的首地址.
    注意,这里的b2的类型是int (*) ,这样表示一个指向二唯数组的指针。再注意,如果这样在堆空间里已经申请了内存,在释放内存的时候要保证每个空间都要释放。
    int (**b3)[2]=new (int(*)[2])[2]; b3表示一个指向(指向二唯数组的指针)的指针,我们在给他申请空间的时候一定要注意它的类型:它是int (*)型的指针,那申请空间的时候的类型为int(*)[元素个数],由于它后边还带个二唯数组每元的个数后缀,所以加上这个后缀就OK了。
    int (**b4)[2];表示每一个元素都指向(指向二唯数组的指针)的数组。
    由于它是数组,所以要是在堆里申请内存,就必须为每一个元素单独申请。
    b4[0]=new (int(*)[2])[2];原理同上

    (3) 指向了一个(指向指针的指针)
        int ** cc=new (int*)[10];
            这种声明很简单因为cc的类型是int*型的指针,所以你要在堆里申请的话就要用(int *)来申请;
    (4) 多唯指针数组的指针数组。
       int ** d[2];表示一个指向指针的指针数组;数组里有两个元素,每一个元素都是一个指针,这个指针指向另一个指针:)
       再怎么变也是数组呀,呵呵,
       如果你读懂了上边的,那下边的声明就很简单了:
       d[0]=new (int *)[10];
       d[1]=new (int * )[10];
    ---------------------------------------

    总结 : 只要知道了其中的指针类型,声明一个指针就很简单了,堆里申请稍微复杂点,不过知道了类型,也就稍微烦琐一点。
      (1)int*ptr;//指针所指向的类型是int

      (2)char*ptr;//指针所指向的的类型是char

      (3)int**ptr;//指针所指向的的类型是int*

      (4)int(*ptr)[3];//指针所指向的的类型是int()[3]


    二 : 函数指针 

    关于函数指针,我想在我们可能需要写个函数,这个函数体内要调用另一个函数,可是由于项目的进度有限,我们不知道要调用什么样的函数,这个时候可能就需要一个函数指针;

    int a();这个一个函数的声明;
    ing (*b)();这是一个函数指针的声明;
    让我们来分析一下,左边圆括弧中的星号是函数指针声明的关键。另外两个元素是函数的返回类型(void)和由边圆括弧中的入口参数(本例中参数是空)。注 意本例中还没有创建指针变量-只是声明了变量类型。目前可以用这个变量类型来创建类型定义名及用sizeof表达式获得函数指针的大小:
    unsigned psize = sizeof (int (*) ()); 获得函数指针的大小
    // 为函数指针声明类型定义
    typedef int (*PFUNC) ();

    PFUNC是一个函数指针,它指向的函数没有输入参数,返回int。使用这个类型定义名可以隐藏复杂的函数指针语法,就我本人强烈建议我们大内弟子使用这种方式来定义;

    下面是一个例子,一个简单函数指针的回调(在GNU编译器上通过,在VC上需要改变一个头文件就OK了)

    #include<iostream>;              //GNU 编译器 g++ 实现
    using namespace std;
    /*                              //vc 的实现
    #include "stdafx.h"
    #include <iostream.h>;
    */

    #define DF(F) int F(){  cout<<"this is in function "<<#F<<endl;\
           return 0;       \
    }
    //声明定义DF(F)替代 int F();函数;
    DF(a); DF(b); DF(c); DF(d); DF(e); DF(f); DF(g); DF(h); DF(i);     //声明定义函数 a b c d e f g h i

    // int (*pfunc)();              //一个简单函数指针的声明
    typedef int(*FUNC)();   //一个函数指针类型的声明

    FUNC ff[] = {a,b,c,d,e,f,g,h,i};   //声明一个函数指针数组,并初始化为以上声明的a,b,c,d,e,f,g,h,i函数

    FUNC func3(FUNC vv){    //定义函数func3,传入一个函数指针,并且返回一个同样类型的函数指针
           vv();
           return vv;
    }

    /*FUNC func4(int (*vv)()){      //func3的另一种实现
           vv();
           return vv;
    }*/

    int main(){
           for(int i=0;i<sizeof(ff)/sizeof (FUNC);i++){  //循环调用函数指针
                   FUNC r=func3(ff[ i ]);
                   cout<<r()<<endl;                //输出返回值,只是返回了0
           }
           return 0;
    }
    到目前为止,我们只讨论了函数指针及回调而没有去注意ANSI C/C++的编译器规范。许多编译器有几种调用规范。如在Visual C++中,可以在函数类型前加_cdecl,_stdcall或者_pascal来表示其调用规范(默认为_cdecl)。C++ Builder也支持_fastcall调用规范。调用规范影响编译器产生的给定函数名,参数传递的顺序(从右到左或从左到右),堆栈清理责任(调用者或 者被调用者)以及参数传递机制(堆栈,CPU寄存器等)。
    好了,先到此为止吧,写这篇文章耗费了基本上快半天的时间了,很多事情还没有做,等改天有时间再回来整理。

       还有很复杂的声明可能也是一种挑战 比如<<Think in c++>;>;里的
    int (*(*f4())[10]();的声明,f4是一个返回指针的函数,该指针指向了含有10个函数指针的数组,这些函数返回整形值;不是这个函数有特别之处,而是Bruce Eckel 说的“从右到左的辨认规则”是一种很好的方法,值得我们去学习,感谢他:)

    最后我想应该跟大家说一下,写程序应该就象我的一个朋友所说的:简单就是美;我们应该遵循一个原则 : KISS (Keep It Simple,Stupid ,尽量保持程序简单 出自 :《Practical C programming》),把自己的程序尽量的简单明了,这是个非常非常好的习惯。

    由于写的匆忙,可能其中有遗漏的地方,大家发现希望能指正:)
    GOOD LUCK !

  • 相关阅读:
    Guake — 一个新的下拉式终端 — LinuxTOY
    登录时提示出错
    WebOS开发环境搭建
    整理Windows Phone 7教程(很全面)
    如何在 Windows Phone 的代码中创建应用程序栏
    Silverlight for Windows Phone Toolkit升级说明
    WindowsPhone控件详解及引用外部控件Silverlight Toolkit
    WindowsPhone统计图表控件 第三方控件visifire
    WindowsPhone第三方控件Resco MobileForms Toolkit 2012
    Hadoop学习与使用之基本操作命令
  • 原文地址:https://www.cnblogs.com/langqi250/p/2772738.html
Copyright © 2011-2022 走看看