新书推介:《语义网技术体系》
作者:瞿裕忠,胡伟,程龚
   XML论坛     W3CHINA.ORG讨论区     计算机科学论坛     SOAChina论坛     Blog     开放翻译计划     新浪微博  
 
  • 首页
  • 登录
  • 注册
  • 软件下载
  • 资料下载
  • 核心成员
  • 帮助
  •   Add to Google

    >> 本版讨论高级C/C++编程、代码重构(Refactoring)、极限编程(XP)、泛型编程等话题
    [返回] 计算机科学论坛计算机技术与应用『 C/C++编程思想 』 → 高级指针话题 查看新帖用户列表

      发表一个新主题  发表一个新投票  回复主题  (订阅本版) 您是本帖的第 8466 个阅读者浏览上一篇主题  刷新本主题   树形显示贴子 浏览下一篇主题
     * 贴子主题: 高级指针话题 举报  打印  推荐  IE收藏夹 
       本主题类别:     
     卷积内核 帅哥哟,离线,有人找我吗?
      
      
      威望:8
      头衔:总统
      等级:博士二年级(版主)
      文章:3942
      积分:27590
      门派:XML.ORG.CN
      注册:2004/7/21

    姓名:(无权查看)
    城市:(无权查看)
    院校:(无权查看)
    给卷积内核发送一个短消息 把卷积内核加入好友 查看卷积内核的个人资料 搜索卷积内核在『 C/C++编程思想 』的所有贴子 访问卷积内核的主页 引用回复这个贴子 回复这个贴子 查看卷积内核的博客楼主
    发贴心情 高级指针话题

    在openssl里出现了大量的指向指针的指针和函数指针,一直不太理解,今天看书上有一章介绍指针的高级话题,赶紧把它记录下来。
      1,指针以及初始化
      指针是一个地址,它指向内存中某个指定类型的值,而操作符*就是访问指向这个地址的数据。讨论一下指针的初始化。
      考虑:
           int *a;
           *a=100;
      也许会觉得这样没有错误,因为(*a)就是int型的,所以把100赋予一个int型的没错。但是我们在这里创建了一个指针变量a,但是没有给a初始化,然后用*操作符去访问它,当然是会出错的。
      2,指向指针的指针,下面分别看几个例子
      char string[3]={'c','d','e'}.定义了三个char型的变量string[0]='c',string[1]='d',string[2]='e'.
      char *pstring={"cde"},定义了一个字符串,其中string[0]='c',string[1]='d',string[2]='e'.
      现在明显可以看出上面两者的联系了。其实string=pstring.
      char string[3][3]={'M','o','n';'T','u','e';'W','e','d'};这样string[0][0]='M',,,,,
      char *pstring[3]={"Mon","Tue","Wed"},定义了三个char *string型的变量。string[0]="Mon",string[0][0]='M'
      char **ppstring.那这个是什么呢,他就是个指向指针的指针,可以直接初始化ppstring=pstring,或者可以ppstring=&(pstring[0]),使用的时候可以完全和*pstring[3]差不多使用了。
      所以指向指针的指针也就是多了一个间接访问而已,只要知道了指针就是地址,*就是去访问地址的数据就可以了。
      
      3,函数指针。
      int (*f)(),前面一个括号迫使间接访问在函数调用之前,那么就是说访问内存中的某个位置的函数。这就是函数指针的概念。
      初始化:int f(int);  int (*pf)(inf)=&f;
      调用方式:int ans=pf(25);
      下面讨论两个具体应用的问题:
      1),回调函数
      我们先看看下面这段程序:
      int comp(int a,int b)
      {
            if(a==b)return 0;
            else return 1;
      }
      完成的功能实在是简单,就是比较一下两个数是否一致。但是你是否发现这个只能比较int型的数据,要是比较char的呢,那必须得重新写一个函数,比较float也得重新写一个,这样是不是有点麻烦,并且易用性也不好,换一个类型就要换一个函数。那么我们考虑是否在comp的时候不传具体的类型呢,因为我们根本也不知道要传什么类型给comp。解决难题的办法就是把参数类型声明为void *,表示"一个指向未知类型的指针"。然后加一个回调函数作为参数,这样在按照不同的类型编写不同的回调函数,在上层就保证了comp函数的易用性。下面请看改写的函数
      int comp(void *a,void *b, int (*compare)(void const *,void const *))
      {
    if(compare(a,b))return 1;
    else return 0;
      }
      int compare_int(void const *a,void const *b)
      {
    if(*(int*)a==*(int*)b) return 0;
    else return 1;
      }
      int compare_char(void const *a,void const *b)
      {
    if(*(char*)a==*(char*)b) return 0;
    else return 1;
      }
    在主函数中可以这样调用
      int a=2;int b=2;
      comp(&a,&b,compare_int);
      char c='d';char d='d';
      comp(&d,&c,compare_char);
      现在在C++中已经有重载和模板的技术了,上面的任务根本不用这么麻烦实现的。但是openssl是用C语言写的,里面大量的void类型,并且大量的指向函数的指针,希望这点讲解对大家看openssl能有点帮助。

      2),转移表
      我们下面看个例子,在一个计算器的例子中,有如下一些语句:
      switch(oper)
      case ADD:
              result=add(op1,op2);
              break;
      case SUB:
              result=sub(op1,op2);
              break;
      case MUL:
              result=mul(op1,op2);
              break;
      case DIV:
              result=div(op1,op2);
              break;
    ...
      对于一个功能复杂的计算器,那么switch语句将非常长。为了使用switch语句,表示操作符的代码必须是整数。如果它们是从零开始连续的整数,我们可以使用转换表来完成这个任务。转换表就是一个函数指针数组。
      创建一个转换表需要两个步骤。首先,声明并初始化一个函数指针数组。唯一需要留心之处就是确保这些函数的原形出现在这个数组的声明之前。
      double add(double,double);
      double sub(double,double);
      double mul(double,double);
      ...
      double (*oper_func[])(double,double)={add,sub,mul,div,...};
      初始化列表中各个函数名的正确顺序取决于程序中用于表示每个操作符的整型代码。这个例子假定ADD是0,SUB是1,MUL是3,,,
      第2个步骤是用下面语句替换前面整条switch语句:
      result=oper_func[oper](op1,op2);
      oper从数组中选择正确的函数指针,而函数调用操作符将执行这个函数。


       收藏   分享  
    顶(0)
      




    ----------------------------------------------
    事业是国家的,荣誉是单位的,成绩是领导的,工资是老婆的,财产是孩子的,错误是自己的。

    点击查看用户来源及管理<br>发贴IP:*.*.*.* 2005/5/24 10:51:00
     
     blackeyes 帅哥哟,离线,有人找我吗?
      
      
      等级:大一新生
      文章:9
      积分:93
      门派:XML.ORG.CN
      注册:2004/10/12

    姓名:(无权查看)
    城市:(无权查看)
    院校:(无权查看)
    给blackeyes发送一个短消息 把blackeyes加入好友 查看blackeyes的个人资料 搜索blackeyes在『 C/C++编程思想 』的所有贴子 引用回复这个贴子 回复这个贴子 查看blackeyes的博客2
    发贴心情 
    部一下仁兄,指针和链表有什么区别没

    ----------------------------------------------
    技术不是问题只要我爱, 我一定可以成功我相信自己~~~~~

    点击查看用户来源及管理<br>发贴IP:*.*.*.* 2005/5/28 12:36:00
     
     sdrk 帅哥哟,离线,有人找我吗?
      
      
      等级:大一新生
      文章:4
      积分:76
      门派:XML.ORG.CN
      注册:2005/6/10

    姓名:(无权查看)
    城市:(无权查看)
    院校:(无权查看)
    给sdrk发送一个短消息 把sdrk加入好友 查看sdrk的个人资料 搜索sdrk在『 C/C++编程思想 』的所有贴子 引用回复这个贴子 回复这个贴子 查看sdrk的博客3
    发贴心情 
    对不起,这指针看不出多高级呀,好像课本上都有的
    有过在BASIC里使用指针概念吗?(这里好像没有BASIC的)
    我觉得那种方法比较高级一点
    点击查看用户来源及管理<br>发贴IP:*.*.*.* 2005/6/10 13:14:00
     
     binaryluo 帅哥哟,离线,有人找我吗?
      
      
      威望:6
      等级:研二(Pi-Calculus看得一头雾水)(版主)
      文章:679
      积分:5543
      门派:IEEE.ORG.CN
      注册:2005/2/19

    姓名:(无权查看)
    城市:(无权查看)
    院校:(无权查看)
    给binaryluo发送一个短消息 把binaryluo加入好友 查看binaryluo的个人资料 搜索binaryluo在『 C/C++编程思想 』的所有贴子 引用回复这个贴子 回复这个贴子 查看binaryluo的博客4
    发贴心情 
    以下是引用blackeyes在2005-5-28 12:36:05的发言:
    部一下仁兄,指针和链表有什么区别没

    有啊。
    指针是C/C++提供的访问内存一种语法机制;链表是数据结构的范畴。链表要用指针实现。

    点击查看用户来源及管理<br>发贴IP:*.*.*.* 2005/6/18 18:23:00
     
     GoogleAdSense
      
      
      等级:大一新生
      文章:1
      积分:50
      门派:无门无派
      院校:未填写
      注册:2007-01-01
    给Google AdSense发送一个短消息 把Google AdSense加入好友 查看Google AdSense的个人资料 搜索Google AdSense在『 C/C++编程思想 』的所有贴子 访问Google AdSense的主页 引用回复这个贴子 回复这个贴子 查看Google AdSense的博客广告
    2024/11/25 22:08:47

    本主题贴数4,分页: [1]

    管理选项修改tag | 锁定 | 解锁 | 提升 | 删除 | 移动 | 固顶 | 总固顶 | 奖励 | 惩罚 | 发布公告
    W3C Contributing Supporter! W 3 C h i n a ( since 2003 ) 旗 下 站 点
    苏ICP备05006046号《全国人大常委会关于维护互联网安全的决定》《计算机信息网络国际联网安全保护管理办法》
    78.125ms