Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

Offsetof and container_of of Linux Macro definition (XIX)

2025-01-24 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Internet Technology >

Share

Shulou(Shulou.com)06/03 Report--

Today we'll take a look at two classic macros in Linux: offsetof and container_of. Let's first take a look at the macro definitions of both of them, as follows

# ifndef offsetof#define offsetof (TYPE, MEMBER) ((size_t) & (TYPE*) 0)-> MEMBER) # endif#ifndef container_of#define container_of (ptr, type, member) ({\ const typeof (type*) 0)-> member) * _ mptr = (ptr);\ (type*) ((char*)) _ mptr-offsetof (type, member);}) # endif

To understand these two macros, let's take a look at what the compiler does. Offsetof is used to calculate the offset position of MEMBER members in TYPE structures. The compiler clearly knows the offset position of the structure member variable, and locates the member variable through the first address and offset of the structure variable. Let's explain it by testing the code.

# include # ifndef offsetof#define offsetof (TYPE, MEMBER) ((size_t) & (TYPE*) 0)-> MEMBER) # endifstruct ST {int I; / 0 int j; / / 4 char c; / / 8}; void func (struct ST* pst) {int* pi = & (pst- > I); / / 0 int* pj = & (pst- > j); / / 4 char* pc = & (pst- > c) / / 8 printf ("pst =% p\ n", pst); printf ("pi =% p\ n", pi); printf ("pj =% p\ n", pj); printf ("pc =% p\ n", pc);} int main () {struct ST s = {0}; func (& s); func (NULL); printf ("offset I:% d\ n", offsetof (struct ST, I)) Printf ("offset j:% d\ n", offsetof (struct ST, j)); printf ("offset c:% d\ n", offsetof (struct ST, c)); return 0;}

Let's see the results.

We see that the address values printed by pst and pi are the same, with J and c plus 4 respectively. It is more obvious to pass NULL as a parameter, while directly calling the offsetof macro has the same effect as NULL. Therefore, its role is obvious, which is used to obtain the offset of the MEMBER in the TYPE structure.

Let's take a look at the container_of macro. Let's first explain ({}), which is a syntax extension of the GNU C compiler. It acts like a comma expression, and the result is the value of the last statement. As shown below

Typeof is a keyword specific to the GNU C compiler. It only works on the compiler and is used to get the type of the variable. The usage is as follows

The final principle is shown in the following figure

Let's program to analyze and explain.

# include # ifndef offsetof#define offsetof (TYPE, MEMBER) ((size_t) & (TYPE*) 0)-> MEMBER) # endif#ifndef container_of#define container_of (ptr, type, member) ({\ const typeof (type*) 0)-> member) * _ mptr = (ptr);\ (type*) ((char*) _ mptr-offsetof (type, member)) }) # endif#ifndef container_of_new#define container_of_new (ptr, type, member) ((type*) ((char*) (ptr)-offsetof (type, member)) # endifstruct ST {int I; / / 0 int j; / / 4 char c; / / 8}; void method_1 () {int a = 0; int b = 0 Int r = (a = 1, b = 2, a + b); printf ("r =% d\ n", r);} void method_2 () {int r = ({int a = 1; int b = 2; a + b;}) Printf ("r =% d\ n", r);} void type_of () {int I = 100; typeof (I) j = i; const typeof (j) * p = & j; printf ("sizeof (j) =% d\ n", sizeof (j)); printf ("j =% d\ n", j); printf ("* p =% d\ n", * p);} int main () {method_1 () Method_2 (); type_of (); struct ST s = {0}; char* pc = & s.c; int e = 0; int* pe = & e; struct ST* pst = container_of (pc, struct ST, c); printf (& s =% p\ n ", & s); printf (" pst =% p\ n ", pst); return 0;}

Let's compile and see the results.

Four warnings were reported during compilation, but it did not affect our output. Take a look at the running result.

The values of the above two outputs r are the same, and they are written in the same way. When calling with the container_of macro, the address values of s and pst are the same. So let's try calling pe with our own defined container_of_new macro. Look at the results.

A warning has been given at compile time that the type of pc is incorrect. Then let's run it and see the results.

We found that the final printed s and pst values are not the same. From this, it can be seen that the native container_of macro writing is a little more complicated, but it is the most secure. Through today's analysis of offsetof and container_of macros, the summary is as follows: 1, the compiler clearly knows the offset position of structure member variables; 2, ({}) is similar to the comma expression, the result is the value of the last statement; 3, typeof only takes effect at compilation time, used to get the type of variable; 4, container_of uses ({}) for type security check.

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Internet Technology

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report