程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> 關於C語言 >> 考考你:根據結構體變量地址反推結構體首地址

考考你:根據結構體變量地址反推結構體首地址

編輯:關於C語言

 【題目】:
    根據一個結構體對象某成員的地址,計算出該結構體對象的首地址。
    【例如】:
struct A
{
    int x;
    int y;
    int z;
}
 
#define GET_HEADER_ADDR(MEMBER) (你來實現)
 
void main()
{
    struct A myTest;
 
    printf("addr is %d",GET_HEADER_ADDR(myTest.z) );
 
}
    不看下面的答案,你來嘗試實現上面這個宏吧。
 
   
【答案與分析過程】
    Linux內核中,用兩個非常巧妙地宏實現了,一個是offsetof宏,另一個是container_of宏,下面講解一下這兩個宏。
1.  offsetof宏
【定義】:#define offsetof(TYPE, MEMBER) ((size_t) & ((TYPE *)0)->MEMBER )
【功能】: 獲得一個結構體變量成員在此結構體中的偏移量。
【例子】:
struct A
{
    int x ;
    int y;
    int z;
};
 
void main()
{
    printf("the offset of z is %d",offsetof( struct A, z )  );
}
 
// 輸出結果為 8
【分析】:
 
該宏,TYPE為結構體類型,MEMBER 為結構體內的變量名。
 
(TYPE *)0) 是欺騙編譯器說有一個指向結構TYPE 的指針,其地址值0
 
(TYPE *)0)->MEMBER 是要取得結構體TYPE中成員變量MEMBER的地址. 因為基址為0,所以,這時MEMBER的地址當然就是MEMBER在TYPE中的偏移了。
 
2. container_of宏(即實現了題目中的功能)
 
【定義】:
 
#define container_of(ptr, type, member)   ({const typeof( ((type *)0)->member ) *__mptr = (ptr); (type *)( (char *)__mptr - offsetof(type,member) );})
 
【功能】:
 
從結構體(type)某成員變量(member)指針(ptr)來求出該結構體(type)的首指針。
 
【例子】:

struct A
{
    int x ;
    int y;
    int z;
};
 
struct A myTest;
 
int *pz = myTest.z;
 
struct A* getHeaderPtr( int *pz )
{
    return container_of( pz , struct A, z );
}

 【分析】:
 (1) typeof( ( (type *)0)->member )為取出member成員的變量類型。

(2) 定義__mptr指針ptr為指向該成員變量的指針(即指向ptr所指向的變量處)

(3) (char *)__mptr - offsetof(type,member)) 用該成員變量的實際地址減去該變量在結構體中的偏移,來求出結構體起始地址。

(4) ({ })這個擴展返回程序塊中最後一個表達式的值。
 
本文出自 “對影成三人” 博客

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved