Article turn from click to open link
Content
0. Intro
1. For example
(1) Code
(2) Inspection results
(3) Why starting from 0.
(4) Results starting from a non-0 address
2. Summary
0. Intro
In the linux-2.26.23 version of the kernel code, the./include/linux/stddef.h file has the following definitions.
00020: #undef offsetof
00021: #ifdef compiler_offsetof
00022: #define OFFSETOF (Type,member) Compiler_offsetof (Type,member)
00023: #else
00024: #define OFFSETOF (Type, member) ((size_t) & ((type *) 0)- >member)
00025: #endif
00026: #endif/* KERNEL/
00027:
00028: #endif
Compiler_offsetof is not the author's concern, the second macro definition is the method discussed in this article.
This macro definition is a good explanation: cast a 0 address to a type pointer, get member, then get the member address, and finally cast the address to the integer representing the size. The integer is the offset of the member.
1. for example
(1) Code
00001:/* * 00002: * Test the offset of a member of a struct 00003: * * 00004:00005: #include <stdio.h> 00006:00007
: typedef struct 00008: {00009:int x; 00010:int y; 00011:int z; 00012:} point; 00013:00014://#define OFFSETOF (Type, member) ((size_t) & ((type*) 0)->member) 00015: #define OFFSETOF (Type, Membe R) ((size_t) & (((type*) 0)->member) 00016:00017:void test1 () 00018: {00019:int x = (size_t) & ((point*) 0
)->x;
00020:int y = (size_t) & ((point*) 0)->y;
00021:int z = (size_t) & (((point*) 0)->z);
00022:printf ("offset:x =%d, y =%d, z =%d\n", x, Y, z); 00023:} 00024:00025:void test2 () 00026: {00027:printf ("point.x offset =%d\n", Offsetof (Point, X)); 00028:prin
TF ("Point.y offset =%d\n", Offsetof (point, y));
00029:printf ("point.z offset =%d\n", Offsetof (point, z)); 00030:} 00031:00032:int Main (int argc, char** argv) 00033: {00034:test1 (); 00035:printf ("\ n"); 00036:test2
(); 00037:return 0; 00038:} 00039:
In this example, I borrowed the Linux kernel method, two ways to achieve
(2) Inspection results
#./offsetof
offset:x = 0, y = 4, z = 8
point.x offset = 0
point.y offset = 4
point.z offset = 8
Needless to say, the result is correct.
(3) Why starting from 0.
From the thought of the method described in section 1th, it can be seen that the purpose of starting from 0 is to eliminate the starting address of the structure body after obtaining the address of a member.
Let's look at the results from a non-0 start.
(4) Results starting from a non-0 address
Modify the Test1 () function, as follows.
00017:void test1 ()
00018: {
00019: int x = (size_t) & ((point*) 1000)->x;
00020: int y = (size_t) & ((point*) 1000)->y;
00021: int z = (size_t) & ((point*) 1000)->z);
00022: printf ("offset:x =%d, y =%d, z =%d\n", x, Y, z);
00023:}
The results are as follows.
#./offsetof
offset:x = 1000, y = 1004, z = 1008 point.x
offset = 0
point.y offset = 4
point.z offset = 8
As you can see, if you start with a non 0, you actually get the actual address of that member (of course, the actual address is relative to the given starting address, not the real memory address). The actual address subtracts the offset of the member after the given starting address.
2. Summary
In this paper, we use the Linux kernel method to illustrate the method of obtaining the member offset of the structure body. The Linux kernel also has n many good structure and algorithm, the author later slowly tells.
Think about problems, and think deeply. Learning the kernel to learn its design ideas and methods, record is to organize their own ideas, in case of forgetting.
Last year and recently interviewed a lot of people, asked this topic, but very few people can answer, this problem is basic skills ah. Do not know how to get the structure member offset of the students, tapping the keyboard, try it. :)