专注电子技术学习与研究
当前位置:单片机教程网 >> MCU设计实例 >> 浏览文章

指针在c语言中的妙用

作者:佚名   来源:本站原创   点击数:  更新时间:2011年03月14日   【字体:

指针,任何一个计算机语言都少不了的好东西。特殊问题,特殊对待。函数指针就是这么一个特殊的例子。比如:

void Run(void)

{

  PORTB = ~PORTB;

}

 

这个函数我们可以直接在main()里调用它,也可以使用指针。如下所示:

void (*fun)(void);

 

int main()

{

fun = Run;

fun();

return 0;
}

   使用指针有很多优点,关于指针的基本概念可以参考的第十六课:http://www.51hei.com/mcuteach/133.html ,如果我们定义了一个指针数组,就可以同时调用多个已知的函数,在不需要调用的时候再将它删除。特别是在C++里,如果定义了一个全局的class,那么我们就可以在构造函数里向指针数组添加一个指针,这个指针指向main()里需要反复调用的程序,那么在编写大型程序的时候维护起来就相当轻松了。下面是我在使用C++类定义的一个函数回调类,它是一个全局的类,在main()之前就已经定义了。

 

typedef void (*PROC)(MESSAGE_TYPE &style,MESSAGE ¶m);
 //定义函数类型,形参为MESSAGE枚举
typedef void (*HANDLER)(void);
 

class Delegate
{
protected:
  
  PROC proc[PROC_SIZE];
  HANDLER pRun[PROC_SIZE];
  
  static void NULLFUNCTION0(void)
  {
  }
  
  static void NULLFUNCTION2(MESSAGE_TYPE &style,MESSAGE ¶m)
  {
  }
  
public:
  
  bool add(PROC fun)//添加回调函数
  {
    char i;
    for(i = 0 ; i < PROC_SIZE ; i++)
    {
      if(proc[i] == NULLFUNCTION2)
      {
         proc[i] = fun;
         return true;
      }
    }
    return false;
  }
  
  bool add(HANDLER fun)// 添加实时运行函数
  {
    char i;
    for(i = 0 ; i < PROC_SIZE ; i++)
    {
      if(pRun[i] == NULLFUNCTION0)
      {
         pRun[i] = fun;
         return true;
      }
    }
    return false;
  }
  
  void clearProc()//清除函数指针
  {
    char i;
    for(i = 0; i < PROC_SIZE ; i++)
    {
      proc[i] = NULLFUNCTION2;
    }
  }
  
  void clearRun()
  {
    char i;
    for(i = 0; i < PROC_SIZE ; i++)
    {
      pRun[i] = NULLFUNCTION0;
    }
  }
  
  bool remove(PROC fun)//删除最后一个匹配的回调
  {
    char i;
    
    i = PROC_SIZE ;
    
    while( i-- )
    {
      if(proc[i] == fun)
      {
        proc[i] = NULLFUNCTION2;
        return true;
      }
    }
    return false;
  }
  
  bool remove(HANDLER fun)// 删除最后一个匹配的回调
  {
    char i;
    
    i = PROC_SIZE ;
    
    while( i-- )
    {
      if(pRun[i] == fun)
      {
        pRun[i] = NULLFUNCTION0;
        return true;
      }
    }
    return false;
  }
  
  bool removeAll(PROC fun)//删除所有匹配的回调
  {
    char i;
    bool deled = false;
    
    for(i = 0; i < PROC_SIZE; i++)
    {
      if(proc[i] == fun)
      {
        proc[i] = NULLFUNCTION2;
        deled = true;
      }
    }
    return deled;
  }
  
  void selectProc(PROC fun)//      选择回调
  {
    clearProc();
    add(fun);
  }
  
  void selectRun(HANDLER fun)//      选择回调
  {
    clearRun();
    add(fun);
  }
  
  void send(MESSAGE_TYPE type,MESSAGE param = WM_NULL)//  发送消息
  {
    char i;
    for(i = 0 ; i < PROC_SIZE ; i++)
    {
      if(proc[i] != NULLFUNCTION2)
      {
        proc[i](type,param);
        if(param == WM_HANDLED)
          return ;
      }
    }
  }
  
  void Run()//运行
  {
    char i;
    for(i = 0 ; i < PROC_SIZE ; i++)
    {
      if(pRun[i] != NULLFUNCTION0)
      {
        pRun[i]();
      }
    }
  }
  
  void operator = (PROC fun)
  {
    selectProc(fun);
  }
  
  void operator = (HANDLER fun)
  {
    selectRun(fun);
  }
  
  void operator += (PROC fun)
  {
    add(fun);
  }
  
  void operator += (HANDLER fun)
  {
    add(fun);
  }
 
  void operator -= (HANDLER fun)
  {
    remove(fun);
  }
  
  void operator -= (PROC fun)
  {
    remove(fun);
  }
  
  Delegate()
  {
    clearProc();
    clearRun();
  }
};
 
Delegate dg;
把它重命名为一个delegate.h;
接下来我们编写另外一个h文件,很简单。
void TEST_out();
 
class TEST
   TEST()
   {
      dg += TEST_out;
      DDRB = 0xFF;
}
 
void out()
{
   PORTB = ~PORTB;
}
};
 
TEST a;
 
void TEST_out()
{
a.out();
}
 
把它保存为test.h;要保存到编译器的默认路径,我使用的是IAR编译器,默认路径为C:\Program Files\IAR Systems\Embedded Workbench 4.0\avr\inc\
 
接下来编写main()函数;
 
#include <iom8.h>
#include <delegate.h>
#include <test.h>
 
int main()
{
 while(1)
 {
     dg.Run();
}
return 0;
}
 
   主函数里几乎什么也没有写,可是你知道这个程序在单片机上运行是什么结果吗?OH,你答对了就是PORTB端口会一直不停的翻转。沿着这个思路,我们可以把TEST改为数码管的驱动,可以多定义几个h文件,通过指针将它们连接起来,这样,我们在main里几乎不用做太多的事情就能解决一切。是不是感觉很爽呢。
关闭窗口

相关文章