Fork me on GitHub

container_of宏定义

 Container_of在Linux内核中是一个常用的宏,用于从包含在某个结构中的指针获得结构本身的指针,通俗地讲就是通过结构体变量中某个成员的首地址进而获得整个结构体变量的首地址。

 

实现方式:

  container_of(ptr, type, member) ;

 

   其实它的语法很简单,只是一些指针的灵活应用,它分两步:

    第一步,首先定义一个临时的数据类型(通过typeof( ((type *)0)->member )获得)与ptr相同的指针变量__mptr,然后用它来保存ptr的值。

    第二步,用(char *)__mptr减去member在结构体中的偏移量,得到的值就是整个结构体变量的首地址(整个宏的返回值就是这个首地址)。

    其中的语法难点就是如何得出成员相对结构体的偏移量?

   

 

通过例子说明,如清单1:

 1 #include <stdio.h>
 2 #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
 3 #define  container_of(ptr, type, member) ({                      \
 4                       const typeof( ((type *)0)->member ) *__mptr = (ptr);    \
 5                        (type *)( (char *)__mptr - offsetof(type,member) );})
 6 struct test_struct {
 7            int num;
 8           char ch;
 9           float f1;
10   };
11  int main(void)
12   {
13           struct test_struct *test_struct;
14           struct test_struct init_struct ={12,'a',12.3};
15           char *ptr_ch = &init_struct.ch;
16           test_struct = container_of(ptr_ch,struct test_struct,ch);
17           printf("test_struct->num =%d\n",test_struct->num);
18           printf("test_struct->ch =%c\n",test_struct->ch);
19           printf("test_struct->ch =%f\n",test_struct->f1);
20           return 0;
21   }

 

 

或者Linux内核中的函数:

struct eg2805_charger {
	struct device *chg_dev;
	struct i2c_client *client;
	struct power_supply batt_psy;
	struct power_supply *usb_psy;
	struct workqueue_struct  *chg_workqueue;
	struct delayed_work chg_delay_work;

	bool	enable_chg;
	bool	recharge;
	unsigned int	chg_type;
	unsigned int 	battery_present;
	unsigned int 	online;
	unsigned int 	temperature;
	unsigned int 	voltage;
	unsigned int	battery_status;
	unsigned int	ichg;
	unsigned int	aicr;
	unsigned int	cv_value;
	unsigned int 	batt_current;

	struct qpnp_vadc_chip	*vadc_dev;

	bool			batt_hot;
	bool			batt_warm;
	bool			batt_cool;
	bool			batt_cold;
	bool			batt_good;
	int				usb_psy_ma;
	struct mutex	icl_set_lock;
};

static void eg2805_charger_work(struct work_struct *work)
{
	u8 buf[50]={0};
	int i=0;
	int ret;
	int temp, voltage;
	int value = 0;
        //第一个参数为work,函数传参下来的;第二个参数为定义的结构体,第三个则是传参下来的里面需要的work_struct
	struct eg2805_charger *eg2805_chg = container_of(work,
				struct eg2805_charger,
                                chg_delay_work.work);

  

C语言中的offsetof()函数用于计算结构体中成员变量相对于结构体起始地址的偏移量。具体用法如下:

  
#include <stddef.h>
#define offsetof(type, member) ((size_t) &((type*)0)->member)

其中,type表示结构体类型,member表示结构体中的成员变量名。

该函数返回一个size_t类型的值,即成员变量相对于结构体起始地址的偏移量。它的实现是通过将指向类型为type的结构体的指针转换为指向类型为void的指针,然后取成员变量member的地址,最后计算这个地址与指针0的差值,得到的结果就是偏移量。

offsetof()函数的主要作用是在进行内存操作时,特别是对结构体成员变量进行操作时,可以通过该函数计算出成员变量的内存地址,从而更加方便地进行操作。

posted @ 2017-12-03 14:30  yooooooo  阅读(3323)  评论(0编辑  收藏  举报