久久婷婷香蕉热狠狠综合,精品无码国产自产拍在线观看蜜,寡妇房东在做爰3,中文字幕日本人妻久久久免费,国产成人精品三上悠亚久久

當前位置:首頁 > 嵌入式培訓 > 嵌入式學習 > 講師博文 > container_of分析

container_of分析 時間:2018-09-27      ;來源:未知

看一個內核非常經典的(de)實現--container_of

這(zhe)個宏(hong)在驅動和內核代碼中(zhong)用的非常(chang)廣泛,下(xia)(xia)面我(wo)們來具體分析下(xia)(xia)。

 container_of作用是(shi)通過結構體某個成(cheng)員地(di)址從而拿(na)到整(zheng)個結構體地(di)址。

原型:container_of(ptr, type, member)

示例:現有(you)一個student結構(gou)體變量并初始化。

struct student stu;

stu.num = 1;

stu.score = 100;

strcpy(stu.name, "zhangsan");

現在(zai)我們假設有(you)結構體(ti)某個成員的(de)地址,比如(ru)score成員的(de)地址也就是(shi)&stu.score,那么怎么拿到(dao)整個結構體(ti)的(de)地址呢?

這就是(shi)上面(mian)宏的作用,看下每(mei)個成員分別(bie)代表什么:

ptr:代(dai)表結構體成員的真實地址

type:結構體的類型

member:結構體成員的名字

對于(yu)上面的(de)例子,假如我(wo)們有個函(han)(han)數(shu)參數(shu)需要傳遞score成員的(de)地址,而(er)函(han)(han)數(shu)內部需要打印出(chu)原(yuan)結構體變量(liang)的(de)num的(de)值,

只需要做如下(xia)操作:

//ptr代(dai)表score成員的地址

void func(float *ptr)

{

struct student *tmp; //定(ding)義一(yi)個結構體指(zhi)針

tmp = container_of(ptr, struct student, score); //先(xian)獲(huo)取到(dao)結構(gou)體變量的地址

printf("num = %d\n", tmp->num); //打印下(xia)

}

 用起來還(huan)是非常(chang)簡單的,下(xia)面看下(xia)內核(he)經典的實現(xian):

中定義

#define container_of(ptr, type, member) ({ \

const typeof(((type *)0)->member) * __mptr = (ptr); \

(type *)((char *)__mptr - offsetof(type, member)); })

看(kan)起來(lai)比較復(fu)雜(za),我(wo)們以上面的例子對宏進行替換得(de)到(dao)如下兩句:

const typeof(((struct student *)0)->score) * __mptr = (ptr);

(struct student *)((char *)__mptr - offsetof(struct student, score));

第一句(ju)定義(yi)了(le)一個__mptr指(zhi)針指(zhi)向了(le)ptr,也就是指(zhi)向了(le)score成(cheng)員(yuan)的地址(zhi),

前面的(de)(de)typeof(((struct student *)0)->score)作用(yong)是取得(de)結(jie)構體中score成員的(de)(de)類型(xing),屬于gcc的(de)(de)一個關鍵字(zi)用(yong)法。

第二(er)句(ju)話用(yong)__mptr(score成(cheng)員(yuan)(yuan)的(de)地(di)址(zhi)),減去score成(cheng)員(yuan)(yuan)在原結構體(ti)中的(de)偏移值,就(jiu)得到(dao)了原結構體(ti)變量的(de)地(di)址(zhi)。

第二句中又牽扯到一個新的(de)宏:offsetof,它的(de)作用就是求某個結構(gou)體成(cheng)員(yuan)在(zai)結構(gou)體的(de)偏移值。看下(xia)原型(xing):

#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)

替換上(shang)面的offsetof(struct student, score)得到結果就是:

((size_t) &((struct student *)0)->score)

非常巧妙,先把0地址轉換為一個(ge)指(zhi)向student的(de)結構體類型的(de)指(zhi)針(zhen),然后取出其score成員的(de)地址,

因(yin)為這個地址是(shi)相對于0地址的,所(suo)以本身值就(jiu)代(dai)表成(cheng)員的偏移(yi)量(liang),size_t是(shi)對地址進行的強轉(zhuan)。

我們再回到container_of的(de)原型,其實它(ta)的(de)第一句話定義新的(de)指針完(wan)全沒有必(bi)要(yao),那么做只是為了規范性(xing),

完(wan)全(quan)可以(yi)改成如下的定義,效(xiao)果(guo)一(yi)樣。

#define container_of(ptr, type, member) ({ \

(type *)( (char *)ptr - offsetof(type,member) );})

也就(jiu)說我們直接用score成員的地址(zhi)減去它的偏移量即可,是不是好(hao)理解多了。

后,來個完(wan)整(zheng)的測(ce)試用例(li):

#include

#include

#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)

#define container_of(ptr, type, member) ({ \

(type *)( (char *)ptr - offsetof(type,member) );})

struct student{

char name[10];

int num;

};

//num只是(shi)num成(cheng)員的地址

void func(int *num_addr)

{

struct student *test;

test = container_of(num_addr, struct student, num);

printf("%s\n", test->name);

}

int main()

{

struct student stu;

strcpy(stu.name, "zhangsan");

stu.num = 3;

func(&stu.num);

}

內(nei)核的list核心鏈(lian)表關鍵的實現就是container_of,理解上面的內(nei)容更有助于我們學(xue)習(xi)list鏈(lian)表。

上一篇:C++中placement new和delete討論

下一篇:變量的存儲類型

熱點文(wen)章推(tui)薦(jian)
華清學員就業榜(bang)單(dan)
高(gao)薪(xin)學員經驗(yan)分(fen)享
熱點新聞推薦
前臺專線:010-82525158 企業培訓洽(qia)談專線:010-82525379 院校合作洽談專線(xian):010-82525379 Copyright © 2004-2022 北京華清遠見科技集團有限公司 版權所有 ,,京公海網安備11010802025203號

回到頂部