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;赋值前
赋值后