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
Recently, I encountered a requirement to display ...
In fact, the three tables above all have three ro...
Preface To modify file permissions in the termina...
Table of contents Mistake 1: Too many columns of ...
I have previously written an article about file t...
Table of contents Preface start A little thought ...
If we want to perform batch operations on a type ...
Table of contents 1. Redux 1.1. Store (librarian)...
Method 1: Download Pycharm and install Download a...
I have found a lot of online resources on this pro...
1. Import the basic style of external CSS files U...
MySQL 5.7 installation We are learning MySQL data...
Preface: As far as I know, currently CSS can only...
Tomcat itself optimization Tomcat Memory Optimiza...
Let's look at the code first: ALTER TABLE rep...