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

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

  • 结构体指针函数应用场景之一--驱动程序编写
  • 结构体的一些基本用法
    • 形式1:先定义结构体类型,再定义变量
    • 形式2:在定义类型的同时定义变量
    • 形式3:直接定义变量,用无名结构体直接定义变量只能一次
  • 结构体指针在嵌入式Linux驱动中的典型应用
  • linux设备驱动之I2C
  • Linux I2C驱动框架(超详细)

原文链接:https://blog.csdn.net/qq_21792169/article/details/50436089

结构体指针函数应用场景之一–驱动程序编写

struct i2c_driver {
	int (*probe)(struct i2c_client *, const struct i2c_device_id *); //probe函数
	struct device_driver driver; //表明这是一个驱动
	const struct i2c_device_id *id_table; //要匹配的从设备信息(名称)
	int (*detect)(struct i2c_client *, struct i2c_board_info *); //设备探测函数
	const unsigned short *address_list; //设备地址
	struct list_head clients; //设备链表
};

struct bus_type i2c_bus_type = {
	.name		= "i2c",
	.match		= i2c_device_match,
	.probe		= i2c_device_probe,
	.remove		= i2c_device_remove,
	.shutdown	= i2c_device_shutdown,
	.pm		= &i2c_device_pm_ops,
};

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

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

#include   /* 标准输入输出头文件 */
#include  /* 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  \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是在定义结构体的同时定义此类型的结构体指针变量

结构体指针在嵌入式Linux驱动中的典型应用

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

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)。

linux设备驱动之I2C

https://herok.blog.csdn.net/article/details/49048549

Linux I2C驱动框架(超详细)

https://blog.csdn.net/weixin_42462202/article/details/91128914?spm=1001.2101.3001.6650.1&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7EOPENSEARCH%7Edefault-1.queryctr&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7EOPENSEARCH%7Edefault-1.queryctr&utm_relevant_index=2

你可能感兴趣的:(Linux,嵌入式MCU,c语言,开发语言,后端)