C++Windows下CONTAINING_RECORD宏的用法和详解
生活随笔
收集整理的這篇文章主要介紹了
C++Windows下CONTAINING_RECORD宏的用法和详解
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
[cpp] view plaincopy print? #include?<Windows.h>?? #include?<stdio.h>?? int?main()?? {?? ????struct?ABCD?? ????{?? ????????int?a;?? ????????int?b;?? ????????int?c;?? ????????int?d;?? ????};?? ????//CONTAINING_RECORD宏的作用就是根據(jù)結(jié)構(gòu)體?? ????//類型和結(jié)構(gòu)體中成員變量地址和名稱則可求出?? ????//該變量所在結(jié)構(gòu)體的指針?? ????ABCD?Abcd?=?{?1,?2,?3,?4?};?? ????//假設(shè)我們知道ABCD結(jié)構(gòu)體中b的地址和名稱求整個?? ????//b所在結(jié)構(gòu)體ABCD的指針?? ????ABCD?*pAbcd?=?CONTAINING_RECORD(?&Abcd.b,?ABCD,?b?);?? ????printf(?"求得ABCD中a:%d?b:%d?c:%d?d:%d\n",?pAbcd->a,?pAbcd->b,?pAbcd->c,?pAbcd->d?);?? ?? ????//這是如何做到的呢?我們來看看CONTAINING_RECORD的表達式:?? ????//((type?*)(?(PCHAR)(address)?-?(ULONG_PTR)(&((type?*)0)->field)))?? ????//我們看最后一部分(&((type?*)0)->field)將0空指針轉(zhuǎn)成type取地址在本例?? ????//就是將空指針轉(zhuǎn)成ABCD*然后指向b這個變量然后在取地址,這個操作的作用就是?? ????//假設(shè)ABCD開始在0x000000內(nèi)存位置上分配內(nèi)存在此基礎(chǔ)上求b的內(nèi)存地址,說白了?? ????//就是求得b的內(nèi)存結(jié)構(gòu)體對齊偏移量,OK求得b的地址我們轉(zhuǎn)成ULONG_PTR類型,然后用實際?? ????//b的內(nèi)存地址減去b的結(jié)構(gòu)體偏移量求得結(jié)構(gòu)體首地址。?? ????//即:?? ????printf(?"---詳解---\n"?);?? ????ABCD?*pTest?=(?ABCD*?)0;????//這種情況是允許的?? ????int?*pB?=?&pTest->b;?????//求b的內(nèi)存地址,在結(jié)構(gòu)體首地址為0的情況下b的內(nèi)存地址其實就是自身的對齊大小偏移量?? ????ULONG_PTR?Offset?=?(?ULONG_PTR?)pB;?//轉(zhuǎn)成數(shù)字?? ????printf(?"b的偏移量:%d\n",Offset?);?? ?????? ????//最后用實際b的地址減b的偏移量的到結(jié)構(gòu)體首地址?? ????ABCD?*pFinal?=?(?ABCD*?)(?(?(?char*?)&Abcd.b?)?-?Offset?);?? ????printf(?"求得ABCD中a:%d?b:%d?c:%d?d:%d\n",?pFinal->a,?pFinal->b,?pFinal->c,?pFinal->d?);?? ????return?0;?? }??
#include <Windows.h>
#include <stdio.h>
int main()
{struct ABCD{int a;int b;int c;int d;};//CONTAINING_RECORD宏的作用就是根據(jù)結(jié)構(gòu)體//類型和結(jié)構(gòu)體中成員變量地址和名稱則可求出//該變量所在結(jié)構(gòu)體的指針ABCD Abcd = { 1, 2, 3, 4 };//假設(shè)我們知道ABCD結(jié)構(gòu)體中b的地址和名稱求整個//b所在結(jié)構(gòu)體ABCD的指針ABCD *pAbcd = CONTAINING_RECORD( &Abcd.b, ABCD, b );printf( "求得ABCD中a:%d b:%d c:%d d:%d\n", pAbcd->a, pAbcd->b, pAbcd->c, pAbcd->d );//這是如何做到的呢?我們來看看CONTAINING_RECORD的表達式://((type *)( (PCHAR)(address) - (ULONG_PTR)(&((type *)0)->field)))//我們看最后一部分(&((type *)0)->field)將0空指針轉(zhuǎn)成type取地址在本例//就是將空指針轉(zhuǎn)成ABCD*然后指向b這個變量然后在取地址,這個操作的作用就是//假設(shè)ABCD開始在0x000000內(nèi)存位置上分配內(nèi)存在此基礎(chǔ)上求b的內(nèi)存地址,說白了//就是求得b的內(nèi)存結(jié)構(gòu)體對齊偏移量,OK求得b的地址我們轉(zhuǎn)成ULONG_PTR類型,然后用實際//b的內(nèi)存地址減去b的結(jié)構(gòu)體偏移量求得結(jié)構(gòu)體首地址。//即:printf( "---詳解---\n" );ABCD *pTest =( ABCD* )0; //這種情況是允許的int *pB = &pTest->b; //求b的內(nèi)存地址,在結(jié)構(gòu)體首地址為0的情況下b的內(nèi)存地址其實就是自身的對齊大小偏移量ULONG_PTR Offset = ( ULONG_PTR )pB; //轉(zhuǎn)成數(shù)字printf( "b的偏移量:%d\n",Offset );//最后用實際b的地址減b的偏移量的到結(jié)構(gòu)體首地址ABCD *pFinal = ( ABCD* )( ( ( char* )&Abcd.b ) - Offset );printf( "求得ABCD中a:%d b:%d c:%d d:%d\n", pFinal->a, pFinal->b, pFinal->c, pFinal->d );return 0;
}
測試結(jié)果:
總結(jié)
以上是生活随笔為你收集整理的C++Windows下CONTAINING_RECORD宏的用法和详解的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Callgrind:调用图生成缓存和分支
- 下一篇: 为何被主流抛弃-江西IDC机房价格为何居