Usage and explanation of CONTAINING_RECORD macro in C ++ Windows, and containing_record macro
Containing record is a very useful technique in C ++ programming, its function is to obtain the base address of a known struct or class, the address of the member in the object, and the struct name or class name. Because it is easy to write, it is used as a macro. # Define CONTAINING_RECORD (address, type, field) \ (type *) (PCHAR) (address)-(ULONG_PTR) (& (type *) 0) -> field )))
# Include
# Include
Int main () {struct ABCD {int a; int B; int c; int d ;}; // The CONTAINING_RECORD macro is used to obtain the pointer ABCD Abcd ABCD = {1, 2, 3, 4}; // assume that we know the address and name of B in the ABCD struct, and find the pointer ABCD * pAbcd = CONTAINING_RECORD (& ABCD. b, ABCD, B); printf ("obtain a: % d B: % d c: % d \ n", pAbcd->, pAbcd-> B, pAbcd-> c, pAbcd-> d); // how does this happen? Let's take a look at the CONTAINING_RECORD expression: // (type *) (PCHAR) (address)-(ULONG_PTR) (& (type *) 0)-> field ))) // Let's take a look at the last part (& (type *) 0)-> field) convert 0 NULL pointer to type to get the address in this example // convert NULL pointer to ABCD * and then point to the variable B and then get the address, the role of this operation is // assume that ABCD begins to allocate memory at the 0x000000 memory location. Based on this, find the memory address of B. To put it bluntly, // obtain the alignment offset of the memory structure of B, OK, obtain the address of B, convert it to the ULONG_PTR type, and then use the actual memory address of // B minus the structure offset of B to obtain the first address of the structure. // Printf ("--- explanation --- \ n"); ABCD * pTest = (ABCD *) 0; // In this case, int * pB = & pTest-> B; // calculate the memory address of B, when the first address of the struct is 0, the memory address of B is actually its own alignment Offset ULONG_PTR Offset = (ULONG_PTR) pB; // convert it to the number printf ("B Offset: % d \ n ", Offset); // Finally, use the actual B address to subtract the B Offset to the first address of the structure, ABCD * pFinal = (ABCD *) (char *) & Abcd. b)-Offset); printf ("obtain a: % d B: % d c: % d \ n", pFinal->, pFinal-> B, pFinal-> c, pFinal-> d); return 0 ;}
Test results: