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

    原创 :彻底了解指针数组,数组指针以及函数指针 [复制链接]

     

    帖子
    60
    主题
    16
    精华
    0
    可用积分
    74
    专家积分
    0
    在线时间
    0 小时
    注册时间
    2003-10-07
    最后登录
    2004-12-06
    论坛徽章:
    0
     
    跳转到指定楼层
    1[收藏(0)][报告]
     
     发表于 2004-07-30 19:23:41 |只看该作者 |倒序浏览
    小弟是一个软件工程师,做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 !
  • 相关阅读:
    VScode 修改中文字体
    missing KW_END at ')' near '<EOF>'
    SQL inner join, join, left join, right join, full outer join
    SQL字符替换函数translater, replace
    SQL COOKBOOK SQL经典实例代码 笔记第一章代码
    sqlcook sql经典实例 emp dept 创建语句
    dateutil 2.5.0 is the minimum required version python
    安装postgresql后找不到服务 postgresql service
    Postgres psql: 致命错误: 角色 "postgres" 不存在
    【西北师大-2108Java】第十六次作业成绩汇总
  • 原文地址:https://www.cnblogs.com/jeanschen/p/3538711.html
Copyright © 2011-2022 走看看