当前位置:网站首页>Offsetof macro and container_ Of macro analysis details
Offsetof macro and container_ Of macro analysis details
2022-07-28 11:04:00 【tutu-hu】
One . summary
offsetof Macro and container_of Macro in linux Kernel has a very wide range of applications . These two macros also have very powerful functions , among offsetof Macro is used to obtain the offset of a variable of the structure relative to the first address of the structure ;container_of Macro is used to deduce the first address of structure variable according to the address of structure member variable . In addition, it is also meaningful to analyze the implementation process of these two macros , It can help us understand C The operation of language on memory . Next, we will analyze its implementation process with specific code .
Two .offsetof macro
<1>offset The function of a macro is : It is used to calculate the offset between an element in the structure and the first address of the structure ( Its essence is to help us calculate through the compiler ).
<2>offset Macro principle : We have a virtual one type Type structure variable , And then use type.member To visit that member Elements , And then we get member The offset from the first address of the entire variable .
<3>offset Macro expression :
// Use offset Macro gets the offset address of the structure variable , among :TYPE Represents the structure type name ,MEMBER Represents the member variable name
#define offsetof(TYPE,MEMBER) ((int)&((TYPE *)0)->MEMBER)
1. Sample code :
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
// Use offsetof Macro gets the offset address of the structure variable , among :TYPE Indicates the structure name ,MEMBER Represents the member variable name
#define offsetof(TYPE,MEMBER) ((int)&((TYPE *)0)->MEMBER)
//64 Bit operating system , Default 8 Byte alignment
struct student
{
char a; //8(4+4)
double b; //8
int c; //8(4+4)
};
int main(int argc,char *argv[])
{
struct student stu1 = {
0};
stu1.b = 11.22;
printf("&stu1 = %p\n",&stu1); // Structure start address
printf("&stu1.a = %p\n",&stu1.a); // member a The address of
printf("&stu1.b = %p\n",&stu1.b); // member b The address of
printf("&stu1.c = %p\n",&stu1.c); // member c The address of
int offset_a = offsetof(struct student,a); // Get member variables a The offset address of
int offset_b = offsetof(struct student,b); // Get member variables b The offset address of
int offset_c = offsetof(struct student,c); // Get member variables c The offset address of
printf("offset_a = %d\n",offset_a);
printf("offset_b = %d\n",offset_b);
printf("offset_c = %d\n",offset_c);
printf("stu1.b = %lf\n",*(double*)((char*)&stu1 + offsetof(struct student,b)));
return 0;
}
2. Result display
Because in linux Environment implementation , The computer is 64 Bit operating system , Default 8 Byte alignment , So member variables a,b,c The address offsets of are 0,8,16. Combined with theoretical analysis, the actual program execution results are as follows :
&stu1 = 0x7ffd4d101490
&stu1.a = 0x7ffd4d101490
&stu1.b = 0x7ffd4d101498
&stu1.c = 0x7ffd4d1014a0
offset_a = 0
offset_b = 8
offset_c = 16
stu1.b = 11.220000
Found not , It is the same as the result of our analysis !
3.offsetof Macro implementation principle analysis
Let's try to analyze ((int)&((TYPE *)0)->MEMBER):
(1)(TYPE *)0 ----------------> (struct student *)0
This is a cast , hold 0 The address coercion type is converted to a pointer , This pointer points to a TYPE Structure variable of type . In fact, this structure variable may not exist , But as long as we don't dereference this pointer, there will be no error . The actual meaning is that we force 0 This address uses TYPE The structure type of type explains . Whether he exists or not , As for why 0 Address ? It is to find the offset address of other member variables more conveniently .
(2)((TYPE *)0)->MEMBER ----------------> ((struct student *)0)->a
In fact, it refers to the member variable through the structure pointer
(3)&((TYPE *)0)->MEMBER ----------------> &(((TYPE *)0)->MEMBER) ----------------> &(((struct student *)0)->a)
The explanation of this sentence should be to obtain the structural variable first , Then take the address of this variable . What you naturally get is the actual address of the structural variable , The modified structure is forcibly placed in 0 address , Therefore, the address of the obtained member variable is the cheap address of the variable . Finally using int Force type conversion .
3、 ... and .container_of macro
<1>container_of The function of a macro is : The first address of the structure variable is derived from the address of the structure member variable .
<2>offset Macro principle : In a word, the address of the current variable minus the offset of the variable ( You can use the above offsetof Macro calculation ) Is the first address of the structure variable .
<3>offset Macro expression :
#define container_of(ptr, type, member) ({ \ const typeof( ((type *)0)->member ) *__mptr = (ptr); \ (type *)( (char *)__mptr - offsetof(type,member) );})
1. Sample code :
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
//<1>offsetof Use of macros
//offset The function of a macro is : Use a macro to calculate the offset between an element in a structure and the first address of the structure ( Its essence is to help us calculate through the compiler ).
// among :TYPE Indicates the structure name ,MEMBER Represents the member variable name
#define offsetof(TYPE,MEMBER) ((int)&((TYPE *)0)->MEMBER)
//<2>container_of Use of macros
// Use container_of The macro is based on the address of the structure member variable , Get the address of the structure variable
// among :ptr It refers to structural elements member The pointer to ,type Is the structure type ,member Is the element name of an element in the structure
// This macro returns a pointer to the entire structure variable , The type is (type *)
#define container_of(ptr, type, member) ({ \ const typeof( ((type *)0)->member ) *__mptr = (ptr); \ (type *)( (char *)__mptr - offsetof(type,member) );})
struct student
{
char a; //8(4+4)
double b; //8
int c; //8(4+4)
};
int main(int argc,char *argv[])
{
struct student stu1 = {
0}; // Define structure variables stu1
struct student *getstu; // Used to receive the obtained structure variable address
getstu = container_of(&stu1.b,struct student,b); // According to the member variable b Get the address of the structure variable and return
printf("getstu = %p\n",getstu); // Print the obtained address
printf("&stu1 = %p\n",&stu1); // Print the actual address
return 0;
}
2. Result display
Calculate the first address of the structure variable and compare it with the original actual address , It can be seen that the calculated address is completely correct !
getstu = 0x7ffce5ec4270
&stu1 = 0x7ffce5ec4270
3.container_of Macro implementation principle analysis
It can be seen that container_of The macro is divided into two pointing statements , The first sentence :const typeof( ((type *)0)->member ) *__mptr = (ptr); The role of is : use first typeof Get the type of the member variable , Then use this type to define a pointer variable __mptr And the address of the member variable ptr Assign to __mptr. such __mptr What's kept in this book is ptr Value .
The second sentence is :(type *)( (char *)__mptr - offsetof(type,member) );}) In fact, it is to use the above offsetof The macro calculates the offset address of the member variable relative to the first address of the structure variable , Then the current address - offset = Structure variable first address . It's a very simple data calculation , A little difficult is right C Understanding of language memory operation and variable type conversion .
边栏推荐
猜你喜欢

3. MapReduce explanation and source code analysis

盘点:令人心动的数据可视化图表

CRM+零代码:轻松实现企业信息化

19. Delete the penultimate node of the linked list

剑指 Offer 06. 从尾到头打印链表

Learn how to do e-commerce data analysis (with operation analysis index framework)

The future of generating confrontation networks in deepfake

ICML 2022 | graph represents the structure aware transformer model of learning

一文学会如何做电商数据分析(附运营分析指标框架)

Blue Bridge Cup embedded Hal library ADC
随机推荐
分体式测斜探头安装要点及注意事项
Here is a super practical excel shortcut set (common + summary of eight categories)
_ HUGE and __ IMP__ HUGE in “math.h“
nodemcu之开发环境配置
表格数据处理软件,除了Excel还有什么?
3. MapReduce explanation and source code analysis
FHWY工作日进度表
GKNoiseMap
Inventory: exciting data visualization chart
GKCylindersNoiseSource
Yan reported an error: could not find any valid local directory for nmprivate/
Array related knowledge points
Blue Bridge Cup embedded Hal library USART_ TX
Zero code | easily realize data warehouse modeling and build Bi Kanban
Make a virtual human with zego avatar | virtual anchor live broadcast solution
RHEL 6.4 安装svn和apache
02.1.2. logic type bool
网络文件系统服务(NFS)
Installation points and precautions of split angle probe
Crm+ zero code: easily realize enterprise informatization