C语言结构体中定义函数指针详解

时间:2022-08-30 19:47:24

在学习嵌入式我们经常和结构体函数指针打交道,还有链表,环形缓冲区之类的,这里中点讲解结构体中定义函数指针。下面这个程序你看一遍你基本也明白用法了。

下面是我写的一个很简单的程序struct.c

#include <stdio.h>  /* 标准输入输出头文件 */
#include <stdlib.h> /* strtoul用到的头文件 */

struct test_pfun                                          { /* 定义一个结构体,里面有三个成员,是三个函数指针 ,前面千万不要加static,这里并没有分配内存*/
int (*add) (int a,int b);
int (*sub) (int a,int b);
int (*mult) (int a,int b);
};

static int  test_add(int a,int b)   /* 定义求和函数 */
{
   return (a+b);
}

static int  test_sub(int a,int b)   /* 定义相减函数 */
{
   return (a-b);
}

static int   test_mult(int a,int b)   /* 定义乘法函数 */
{
   return (a*b);
}

struct test_pfun pfun={    /* 关键的地方时在这里,看怎么函数指针赋值 */
 .add   =test_add,
 .sub   =test_sub,
 .mult  =test_mult,
};

/*
*  usage:
*  ./a.out num1 num2 
*/
void print_uage()
{
   printf("./a.out <num1> <num2>\n ");    /* 打印用法 */
}

int main(int argc,char **argv)
{
   int a ,b;  
   if(argc!=3)
   {
 print_uage();
return -1;
   }
  a=strtoul(argv[1],NULL,0);    /* 把字符串argv[1]转换成一个整数a */
  b=strtoul(argv[2],NULL,0);   /* 把字符串argv[2]转换成一个整数b */


/* 不懂strtoul命令的请点击这里:点击这里! */

printf("a+b=%d\n",pfun.add(a,b));
printf("a-b=%d\n",pfun.sub(a,b));
printf("a*b=%d\n",pfun.mult(a,b));
   return 0;
}

下面我在讲一下结构体的一些基本用法:

形式1:先定义结构体类型,再定义变量
struct结构体标识符
{
成员变量列表;…
};
struct 结构体标识符 *指针变量名;

变量初始化一:struct结构体标识符 变量名={初始化值1,初始化值2,…, 初始化值n };

形式2:在定义类型的同时定义变量
struct结构体标识符
{
成员变量列表;…
} *指针变量名;


形式3:直接定义变量,用无名结构体直接定义变量只能一次
struct
 {
成员变量列表;…
}*指针变量名;

其中“指针变量名”为结构体指针变量的名称。形式1是先定义结构体,然后再定义此类型的结构体指针变量;形式2和形式3是在定义结构体的同时定义此类型的结构体指针变量


最后我在举一个驱动中的典型例子:

struct button_irq_desc {   /* 定义一个结构体,只是定义这种类型。再次强调前面不要加上static ,现在还没有分配内存 */
    int irq;
    unsigned long flags;
    char *name;
};

/* 用来指定按键所用的外部中断引脚及中断触发方式, 名字 */
static struct button_irq_desc button_irqs [] = {    /* 定义一个button_irq_desc结构体类型名字button_irqs的4元数组,这里就可以加上上static ,你定义变量当然得分配内存空间 */
    {IRQ_EINT19, IRQF_TRIGGER_FALLING, "KEY1"}, /* K1 */
    {IRQ_EINT11, IRQF_TRIGGER_FALLING, "KEY2"}, /* K2 */
    {IRQ_EINT2,  IRQF_TRIGGER_FALLING, "KEY3"}, /* K3 */
    {IRQ_EINT0,  IRQF_TRIGGER_FALLING, "KEY4"}, /* K4 */
};


request_irq(IRQ_EINT0,  buttons_irq, IRQF_TRIGGER_FALLING|IRQF_TRIGGER_RISING, "S2", &pins_desc[0]);

struct pin_desc * pindesc = (struct pin_desc *)dev_id;    /* 强制转换成struct pin_desc *指针,这儿是驱动程序的用法 ,看不懂没有关系*/


这里我们还可以定义结构体指针对数组操作:

static struct button_irq_desc    *p_irq_desc=button_irqs;   /* 结构体数组的首地址 */

使用数组中其他选项时候,只需让p_irq_desc这个地址加一,这里加一等于地址加上sizeof(p_irq_desc)。