A. 如何根据结构体的某个成员变量地址,计算结构体的地址,也就是获取结构体的首地址
要回答这个问题之前,我们先抛出一个问题:
question:结构体的成员变量在内存中是如何分布的?
如下有一个tInstance结构体定义,那么tInstance结构体的各个成员变量在内存中是如何分布的呢?先不考虑强制对齐问题
struct A
{
char a; //在32位的cpu中,占1个字节
double b; //在32位的cpu中,占8个字节
short c; //在32位的cpu中,占2个字节
int d; //在32位的cpu中,占4个字节
} tInstance;
结构体tInstance在内存中的分布如下:(未考虑大端和小端模式的问题,在我们这个问题中,也不需要考虑大端和小端的差别)
根据图可知,内存分配满足如下两个条件
(1)前一个成员变量存在低地址,后一个成员变量存在高地址
(2)每个成员变量所在的地址,是它所占字节数的整数倍
此时假设我们有b字段的地址,如何获取结构体的起始地址呢?显然有了b字段的地址,用b的实际地址减去b在结构体中的偏移地址,就可以获取到结构体的起始地址了,显然如下的公式是成立的:
结构体的起始地址 = b字段的实际地址 - b字段在结构体中的相对地址;
那么现在问题就转变为如何获取b字段在结构体中的相对地址,我们看下面的宏,仔细分析它的宏实现
/* ptr表示结构体中的某个成员变量的实际地址,注意这是一个指针
* type表示结构体类型
* member表示结构体成员变量,注意这是一个成员变量名
*/
#define container_of(ptr, type, member) \
(type *)((char *)ptr - (char *)&(((type *)0)->member))
因此,对于我们上面的A结构体,假设我们的成员变量b的地址是pb,那么指向这个成员变量b的结构体的指针就可以按照下面的计算方式计算(比如说结构体m_dev,我们知道它的成员变量b的地址)
struct A *pm_dev = container_of(pb, struct A, b);
B.