指针在c语言中的妙用

发布者:电子设计艺术家最新更新时间:2012-08-25 来源: 51hei关键字:指针  c语言  计算机语言 手机看文章 扫描二维码
随时随地手机看文章

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

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
#include
#include
 
int main()
{
 while(1)
 {
     dg.Run();
}
return 0;
}
 
   主函数里几乎什么也没有写,可是你知道这个程序在单片机上运行是什么结果吗?OH,你答对了就是PORTB端口会一直不停的翻转。沿着这个思路,我们可以把TEST改为数码管的驱动,可以多定义几个h文件,通过指针将它们连接起来,这样,我们在main里几乎不用做太多的事情就能解决一切。是不是感觉很爽呢。
关键字:指针  c语言  计算机语言 引用地址:指针在c语言中的妙用

上一篇:在编程中基于事件驱动的好处
下一篇:于GPS_CHECKTIAMER串口收发程序

推荐阅读最新更新时间:2024-03-16 13:06

51单片机C语言学习4
第四课 数据类型   先来简单说说C语言的标识符和关键字。标识符是用来标识源程序中某个对象的名字的,这些对象可以是语句、数据类型、函数、变量、数组等等。C语言是大小字敏感的一种高级语言,如果我们要定义一个定时器1,可以写做 Timer1 ,如果程序中有 TIMER1 ,那么这两个是完全不同定义的标识符。标识符由字符串,数字和下划线等组成,注意的是第一个字符必须是字母或下划线,如 1Timer 是错误的,编译时便会有错误提示。有些编译系统专用的标识符是以下划线开头,所以一般不要以下划线开头命名标识符。标识符在命名时应当简单,含义清晰,这样有助于阅读理解程序。在C51编译器中,只支持标识符的前32位为
[单片机]
51单片机中断入口地址在c语言中的表示
函数类型 函数名(随便) 中断标识(不同的数字代表不同中断入口) 例如: void INT () interrupt 0 //外部中断0 {} void INT () interrupt 1 //定时/计数器0 {} void INT () interrupt 2 //外部中断1 {} void INT () interrupt 3 //定时/计数器1 {} void INT () interrupt 4 //串口 {} interrupt X 其中X表示中断号, 0表示外部中断0 1表示定时器0溢出中断 2表示外部中断1(/INT1) 3表示定时器1溢
[单片机]
单片机_指针读取内容解析
STC单片机自带内部参考电压,单片机生产时内部已经做校准,可分别在ram和rom中读取, (1)rom中读取 在rom中读取的时候,需要在下载时候勾选下载软件中的 在程序区的结束处添加重要测试参数,如下图所示: 勾选下载后,BandGap电压以mV为单位可以读取。 BGV = (int code *)0xeff7; ROM容量大小不同,地址不同如// STC8A8K60S4A10 是0xeff7 code 是指程序存储(rom)地址 (2)ram中读取 而在ram中不需要勾选(在程序区的结束处添加重要测试参数),放在在idata区域,读取时候用如下程序①(官方例程): #include reg
[单片机]
单片机_<font color='red'>指针</font>读取内容解析
AVR AD转换的C语言编程
#include io8535v.h #define uchar unsigned char #define uint unsigned int uchar Table ={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f}; uchar Da ta ={0,0,0,0}; void DelayMs(uint i) //0.25ms {uchar j; for(;i!=0;i--) {for(j=250;j!=0;j--) {;}} } void Display(uchar *p) //间隔5ms显示 {uchar i,sel=0x01; for(i=0;i 4;i++)
[单片机]
数码管滚动显示C语言程序设计
#include reg52.h //51芯片管脚定义头文件 #include intrins.h //内部包含延时函数 _nop_(); #define uchar unsigned char #define uint unsigned int uchar display ={0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, 0xBF,0xBF,0x89,0x86,0xC7,0xC7,0xC0,0xBF,0xBF, // --H E L L O - 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff}; uchar shift,j=0; /******
[单片机]
Windows服务程序的C语言编写步骤
  Windows 服务被设计用于需要在后台运行的应用程序以及实现没有用户交互的任务。为了学习这种控制台应用程序的基础知识,C(不是C++)是最佳选择。本文将建立并实现一个简单的服务程序,其功能是查询系统中可用物理内存数量,然后将结果写入一个文本文件。最后,你可以用所学知识编写自己的 Windows 服务。   当初我写第一个NT 服务时,我到 MSDN 上找例子。在那里我找到了一篇 Nigel Thompson 写的文章:“Creating a Simple Win32 Service in C++”,这篇文章附带一个 C++ 例子。虽然这篇文章很好地解释了服务的开发过程,但是,我仍然感觉缺少我需要的重要信息。我想理解通过什
[单片机]
单片机内的简要C语言基础
ifdef条件编译 单片机程序开发过程中,经常会遇到一种情况,当满足某条件时对一组语句进行编译,而当条件不满足时则编译另一组语句。 条件编译命令最常见的形式为: #ifdef 标识符 程序段1 #else 程序段2 #endif extern变量申明 C语言中extern可以置于变量或者函数前,以表示变量或者函数的定义在别的文件中,提示编译器遇到此变量和函数时在其他模块中寻找其定义。 注:这里面要注意,对于extern申明变量可以多次,但定义只有一次。 例如: main.c 文件中 u8 id;//定义只允许一次 main() { id=1; printf( d% ,id);//id=1 test(); prin
[单片机]
C++类指针指向子类还是基类的判断方法
#include iostream.h class animal { public: animal() { cout hello kitty endl; } virtual void eat() { cout eat bianbian endl; } }; class plant:public animal { public: plant() { } void eat() { cout haha endl; } }; void fn(animal *pan) { pan- eat (); } void main() { plant st; an
[单片机]
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
  • 学习ARM开发(16)
    ARM有很多东西要学习,那么中断,就肯定是需要学习的东西。自从CPU引入中断以来,才真正地进入多任务系统工作,并且大大提高了工作效率。采 ...
  • 学习ARM开发(17)
    因为嵌入式系统里全部要使用中断的,那么我的S3C44B0怎么样中断流程呢?那我就需要了解整个流程了。要深入了解,最好的方法,就是去写程序 ...
  • 学习ARM开发(18)
    上一次已经了解ARM的中断处理过程,并且可以设置中断函数,那么它这样就可以工作了吗?答案是否定的。因为S3C44B0还有好几个寄存器是控制中 ...
  • 嵌入式系统调试仿真工具
    嵌入式硬件系统设计出来后就要进行调试,不管是硬件调试还是软件调试或者程序固化,都需要用到调试仿真工具。 随着处理器新品种、新 ...
  • 最近困扰在心中的一个小疑问终于解惑了~~
    最近在驱动方面一直在概念上不能很好的理解 有时候结合别人写的一点usb的例子能有点感觉,但是因为arm体系里面没有像单片机那样直接讲解引脚 ...
  • 学习ARM开发(1)
  • 学习ARM开发(2)
  • 学习ARM开发(4)
  • 学习ARM开发(6)
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
随便看看
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved