Get the struct structure address through the struct Member Address, struct Member
1. Problem description:
A struct is defined:
Struct Foo
{
Int;
Int B;
};
Foo foo;
If the program can only get the address of foo. B Due to parameter passing by the function, it wants to obtain other members in the foo struct in some way.
The problem arises, which is the main content discussed below.
2. Overview
Forcibly convert address 0 to a struct pointer. pseudocode: struct foo * p = (struct Foo *) 0;
In this way, the memory offset of the known struct member is obtained through the address of the known struct member minus the first address of the struct member. pseudo code: offset = & (p-> B)-p;
The problem is simple. Now we know the address of foo. B and subtract the offset to get the first address of the struct.
3. Implementation example
//file name : list_head.c#include <stdio.h>struct list_head{ struct list_head *next;};struct fox{ unsigned int tail_color; unsigned int tail_length; struct list_head list;};#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER )#define container_of(ptr, type, member) ({\ const typeof( ((type *)0)->member)* __mptr = (ptr);\ (type *)((char*)__mptr - offsetof(type, member));}) int main(int argc, char** argv){ unsigned short offset = 0; struct fox *p = 0; struct fox red_fox; red_fox.tail_color = 45; red_fox.tail_length = 10; unsigned int *p_t; printf("red_fox_addr: %x\n", &red_fox); printf("tail_color_addr: %x\n", &(red_fox.tail_color)); printf("tail_length_addr: %x\n", &(red_fox.tail_length)); printf("list_addr: %x\n", &(red_fox.list));// offset = (unsigned char*)&(p->list) - (unsigned char*)p; offset = offsetof(struct fox, list); printf("offset: %d \n", offset); p_t = container_of(&red_fox.list, struct fox, list); printf("red_fox_addr: %x\n", p_t); printf("tail_color: %d \n", ((struct fox *)p_t)->tail_color); printf("tail_length: %d \n", ((struct fox *)p_t)->tail_length); return 0;}
4. Application
This method is used for Data Structure Single-Chain tables in Linux. The advantage is also obvious. When you want to use a single-chain table to implement the encapsulated data structure, you do not need to define the pointers and related functions for single-chain table traversal in a separate struct, you only need to include the list_head struct. The kernel provides complete and efficient APIs for single-chain table operations.
The author's ability is limited. If any error is found, please correct it.