In c programming, we use structures to store variables of different data types in one kind of variable. Each variable in the structure is termed as a member of the structure. The memory allocation for these members is always sequential.
Example
In the above structure the addresses allocated for members "i" and "ch" will be sequential in the memory.
Using this property of the structure, if we know the pointer to a member of the structure we can retrieve the pointer to the structure with the help offsetof function.
In the post "offset of" we saw how we can retrieve the offset of a member with in the structure.
As the size occupied by each data type is fixed once we know the offset of the member and its pointer, we can subtract the offset from the pointer to get a pointer to the structure.
For example in the above structure if the pointer to the "char ch" is 1000. The offset of function will return 4 for "ch" as it is after an integer in the structure.
Thus the pointer to the structure would be "1000-4 = 996".
The same is shown in the example code below.
We allocate memory for one structure,test1, of type "temp" and assign values to "i" and "ch".
Then we assign the pointer of ch to a char pointer.
Then we subtract the offset of "ch" from the pointer and assign the return value to a new pointer to a structure,test2, of type temp.
If the pointer assigned to test2 is the correct , we should be able to access the value of "i" using test2.
Thus we print the value of "i" using test2
Here is the full code
struct_ptr.c
Compile and execute it.
Thus we can see that we were able to retrieve the pointer to the parent structure from the pointer to the member.
The same steps are used in the container_of function which is used in the linux kernel code.
By passing pointer to the member of the structure in ptr and the structure type as argument type and the name of the member of which ptr is the pointer to we can retrieve the pointer to the parent structure just as we did in the example above.
Example usage in kernel code :
File leds.c
By passing a pointer to the cdev structure,the structure type as "versatile_led" and the member of the structure as cdev we are able to get a pointer to the structure that contains the cdev and hence get access to other members of the structure.