1. How are structures stored in memory?int main() { Student stu; stu.id = 123456; strcpy(stu.name,"feizhufeifei"); stu.math = 90; stu.PE = 80; printf("Student:%p\r\n",&stu); printf("stu.ID:%p\r\n",&stu.ID); printf("stu.name:%p\r\n",&stu.name); printf("stu.math:%p\r\n",&stu.math); return 0; } The print results are as follows: //The address of the structure Student:0xffffcbb0 //The address of the first member of the structure stu.ID:0xffffcbb0 //Offset address + 0 stu.name:0xffffcbb4//Offset address + 4 stu.math:0xffffcbd4 //Offset address + 24 We can see that the address of the structure is the same as the address of the first member of the structure. This is why we mentioned in Refuse to reinvent the wheel! How to port and use the Linux kernel's general linked list (with complete code implementation) why struct list_head should be placed first in the structure. If you don’t quite understand, take a look at these two examples:
We can see that the member variables in the structure are actually stored as offset addresses in memory. That is to say, the address of structure A + the offset address of the member variable = the starting address of the structure member variable. Therefore, we can also infer the address of structure A based on the starting address of the structure variable and the offset address of the member variable. 2. container_of macro#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)); }) ??First, let’s look at the three parameters. ptr is the pointer to the member variable, type refers to the type of the structure, and member is the name of the member variable. The function of the container_of macro is to find the address of a structure variable through the address of a member variable in the structure, the variable name, and the structure type. A trick used here is to use compiler technology, which is to first find the offset of the structure member in the structure, and then find the address of the main structure variable based on the address of the member variable. The following is a detailed analysis of each part. 3. typeofFirst, let’s look at typeof, which is used to return the type of a variable. This is an extended function of the GCC compiler, which means that typeof is compiler-dependent. It is neither required by the C language specification nor part of a standard. int main() { int a = 5; //Here define a variable b of the same type as a typeof(a) b = 6; printf("%d,%d\r\n",a,b);//5 6 return 0; } 4. (((type *)0)->member)((TYPE *)0) converts 0 to a structure pointer of type type. In other words, it makes the compiler think that the structure starts at the beginning of the program segment, 0. If it starts at address 0, the address of the member variable we get is directly equal to the offset address of the member variable. (((type *)0)->member) refers to the MEMBER member in the structure. typedef struct student{ int id; char name[30]; int math; }Student; int main() { //Here, the structure is forced to be converted to address 0, and then the address of name is printed. printf("%d\r\n",&((Student *)0)->name);//4 return 0; } 5. const typeof(((type * )0) ->member)*__mptr = (ptr); This code means to use Why not just use 6. offsetof(type, member))
size_t is defined in the standard C library and is generally defined on 32-bit architectures as:
On 64-bit architectures it is defined as:
As you can see from the definition, size_t is a non-negative number, so size_t is usually used for counting (because counting does not require a negative area):
In order to make the program more portable, the kernel uses 7. (type * )((char * )__mptr - offsetof(type, member)) This sentence means converting 8. Examples#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) );}) typedef struct student { int id; char name[30]; int math; }Student; int main() { Student stu; Student *sptr = NULL; stu.id = 123456; strcpy(stu.name,"zhongyi"); stu.math = 90; sptr = container_of(&stu.id,Student,id); printf("sptr=%p\n",sptr); sptr = container_of(&stu.name,Student,name); printf("sptr=%p\n",sptr); sptr = container_of(&stu.math,Student,id); printf("sptr=%p\n",sptr); return 0; } The results are as follows:
Macro expansion may make it clearer int main() { Student stu; Student *sptr = NULL; stu.id = 123456; strcpy(stu.name,"zhongyi"); stu.math = 90; //Expand and replace sptr = ({ const unsigned char *__mptr = (&stu.id); (Student *)( (char *)__mptr - ((size_t) &((Student *)0)->id) );}); printf("sptr=%p\n",sptr); //Expand and replace sptr = ({ const unsigned char *__mptr = (&stu.name); (Student *)( (char *)__mptr - ((size_t) &((Student *)0)->name) );}); printf("sptr=%p\n",sptr); //Expand and replace sptr = ({ const unsigned int *__mptr = (&stu.math); (Student *)( (char *)__mptr - ((size_t) &((Student *)0)->math) );}); printf("sptr=%p\n",sptr); return 0; } This is the end of this article about the detailed explanation of the Container_Of macro in the Linux kernel. For more information about the Container_Of macro in the Linux kernel, please search for previous articles on 123WORDPRESS.COM or continue to browse the following related articles. I hope you will support 123WORDPRESS.COM in the future! You may also be interested in:
|
<<: Practical MySQL + PostgreSQL batch insert update insertOrUpdate
>>: Introduction to the use of this in HTML tags
Example Usage Copy code The code is as follows: &l...
Run the command: glxinfo | grep rendering If the ...
Table of contents When setting up a MySQL master-...
Preface Hello everyone, I am Liang Xu. At work, w...
This article example shares the specific code for...
Table of contents 1. Development Environment 2. I...
Let’s build the data table first. use test; creat...
1. View existing modules /usr/local/nginx/sbin/ng...
MySQL's MyISAM and InnoDB engines both use B+...
Implemented according to the online tutorial. zab...
Table of contents 1. Introduce cases 2. View the ...
Implementing carousel with a single DOM node You ...
Table of contents 1. Achieve results 2. Implement...
1. Overview This article systematically explains ...
Controversy over nofollow There was a dispute bet...