使用指针增强C语言程序模块化的几种常用方法

1.指针的增量
定义结构体A
typedef struct
{
uint8_t valid;
uint8_t threshold;
uint8_t count;
uint8_t state;
}S_A;

定义由结构体A组成的结构体B
typedef struct
{
uint8_t auchar;
S_A a1;
S_A a2;
S_A a3;
S_A a4;
}S_B;

声明一个变量:S_B b1;
如果要对b1的成员a1 a2 a3的valid成员赋值,采用如下方法变得简洁优美。
S_A *ptr = (S_A *)&b1.a1.valid;
for(i=0;i<4;i++)
{
(ptr+i)->valid = 0;
}

2.程序模块化中的静态变量
有文件AFile.c和AFile.h,
里面定义了结构体AStruct,为避免全局变量满天飞,声明静态变量static Astruct Astruct1 ;
如何在文件BFile.c中对Astruct1 变量操作呢?以下为操作步骤:
2.1.在AFile.c中定义函数getAStructPtr();
AStruct * getAStructPtr(void)
{
AStruct * TempPtr;
TempPtr = &AStruct1;
return TempPtr;
}
2.2 AFile.h中声明函数
AStruct * getAStructPtr(void);
2.3
BFile.c中包含AFile.h,
调用getAStructPtr函数;
AStruct * Ptr = getAStructPtr();
通过操作Ptr指针,即可对Astruct1 变量成员读写。
这种方式有点类似于C++对象的方法,只不过C++的方法封装在对象内部,C函数与变量写在同一个文件中。
3.利用函数指针,实现程序自动调用不同的回调函数。
程序实现按下不同按键时,配置不同的定时器,执行不同的回调函数。
如果K1按键按下,启动定时器,50000us后在定时器中断中执行函数TIM_CallBack1函数;
如果K1按键按下,启动定时器,60000us后在定时器中断中执行函数TIM_CallBack2函数;

3.1

switch (ucKeyCode)
{
case KEY_DOWN_K1:
	bsp_StartHardTimer(50000, (void *)TIM_CallBack1);
	break;
 case KEY_DOWN_K1:
	bsp_StartHardTimer(60000, (void *)TIM_CallBack2);		
	break;
default:
	break;

}

TIM_CallBack1和TIM_CallBack2是两个不同的邮箱消息发送函数。

static void TIM_CallBack1(void)
{
 /* 如果消息邮箱还有空间,向消息邮箱发送数据 */
 if (isr_mbx_check (&mailbox) != 0)
 {
  s_ucCount1++;
  isr_mbx_send (&mailbox, &s_ucCount1);  
 }
}

static void TIM_CallBack2(void)
{
 /* 如果消息邮箱还有空间,向消息邮箱发送数据 */
 if (isr_mbx_check (&mailbox) != 0)
 {
  s_ucCount2++;
  isr_mbx_send (&mailbox, &s_ucCount2);  
 }
}

bsp_StartHardTimer函数原型如下:

void bsp_StartHardTimer(uint32_t _uiTimeOut, void * _pCallBack)
{
	 SetTimer(_uiTimeOut);
	 s_TIM_CallBack = (void (*)(void))_pCallBack;//函数指针赋值,关键点
	 StartTimer();
}

3.2 s_TIM_CallBack 是从哪里来呢?s_TIM_CallBack是中断函数文件timer.c中定义的静态函数指针变量,与bsp_StartHardTimer定义同文件;

static void (*s_TIM_CallBack1)(void);//与变量及指针函数不同,函数指针声明要加括弧。

单独声明,没有函数体,指针值为默认值。

3.3 s_TIM_CallBack 回调函数又怎么使用?timer.c中使用如下:

void TIM_IRQHandler(void)
{
	TIM_ClearITPendingBit();
	s_TIM_CallBack();//执行回调函数

}

3.4 一点改进
如果回调函数s_TIM_CallBack定义、使用与赋值一般是在同一个文件,实际函数体TIM_CallBack1和TIM_CallBack2可能不在同一个文件,使用bsp_StartHardTimer连接,
bsp_StartHardTimer调用应该与参数TIM_CallBack1\TIM_CallBack2同一个文件,否则TIM_CallBack1\TIM_CallBack2不应该加static前缀。

#if 0
是否可以参照2.程序模块化中的静态变量引入回调函数的指针?

例如:
void (* )getAFunctionPtr(void)
{
void (* FunctionPtr)(void);
FunctionPtr= &s_TIM_CallBack;
return FunctionPtr;
}

先在timer.c文件中声明getAStructPtr函数,
函数赋值处替换为:
void(* )CallbackPtr(void);
CallbackPtr = getAStructPtr(void);// 得到回调函数指针的地址
#endif

因为对于函数s_TIM_CallBack,s_TIM_CallBack、&s_TIM_CallBack和*s_TIM_CallBack的值都是相同的,未赋值前回调函数addptr值为0000000,变量地址已分配

4.函数指针的地址
u8 add(u8 a,u8 b)
{

u8 c;
c=a+b;
return c;
}
u8 (*addptr)(u8 a,u8 b);
addptr = add;

addptr = add;赋值前
在这里插入图片描述
赋值后
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值