色yeye在线视频观看_亚洲人亚洲精品成人网站_一级毛片免费播放_91精品一区二区中文字幕_一区二区三区日本视频_成人性生交大免费看

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

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

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

這個宏在驅動和內核代碼中用的非常廣泛,下面我們來具體分析下。

container_of作用是通過結構體某個成員地址從而拿到整個結構體地址。

原型:container_of(ptr, type, member)

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

struct student stu;

stu.num = 1;

stu.score = 100;

strcpy(stu.name, "zhangsan");

現在我們假設有結構體某個成員的地址,比如score成員的地址也就是&stu.score,那么怎么拿到整個結構體的地址呢?

這就是上面宏的作用,看下每個成員分別代表什么:

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

type:結構體的類型

member:結構體成員的名字

對于上面的例子,假如我們有個函數參數需要傳遞score成員的地址,而函數內部需要打印出原結構體變量的num的值,

只需要做如下操作:

//ptr代表score成員的地址

void func(float *ptr)

{

struct student *tmp; //定義一個結構體指針

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

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

}

用起來還是非常簡單的,下面看下內核經典的實現:

中定義

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

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

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

看起來比較復雜,我們以上面的例子對宏進行替換得到如下兩句:

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

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

第一句定義了一個__mptr指針指向了ptr,也就是指向了score成員的地址,

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

第二句話用__mptr(score成員的地址),減去score成員在原結構體中的偏移值,就得到了原結構體變量的地址。

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

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

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

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

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

因為這個地址是相對于0地址的,所以本身值就代表成員的偏移量,size_t是對地址進行的強轉。

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

完全可以改成如下的定義,效果一樣。

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

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

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

后,來個完整的測試用例:

#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只是num成員的地址

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);

}

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

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

下一篇:變量的存儲類型

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

回到頂部

主站蜘蛛池模板: 黄色免费高清网站 | 艳妇臀荡乳欲伦69调教视频 | 18禁无遮挡无码国产免费网站 | 五月天色站| 亚洲AV第一页国产精品 | 曰本女人牲交全过程免费观看 | 欧美裸体xxxx极品 | 免费看黄色电视 | 久久人妻无码中文字幕第一 | 国产欧美在线不卡 | 无遮挡在线观看 | 亚洲性高清SUV | 婷婷五月综合人人网 | 亚洲AV无码专区在线亚 | 国产做爰又粗又大的视频 | 两个人看的WWW在线观看 | 欧美疯狂xxxxbbbb牲交 | 亚洲AV女人18毛片水真多 | XXX舌L伦农村人XXX | 丰满少妇被猛烈进入A片 | 一个添下面两个吃奶 | 新版天堂资源中文www官网 | 亚洲无人区一码二码三码区别 | 手机真实国产乱子伦对白视频 | 亚洲AV日韩综合一区久热 | 亚洲色无码专区在线观看 | 国产精品久久久久影院亚瑟 | 国产精品偷伦视频观看免费 | 中文字幕一区二区在线观看 | 欧美精品狠狠色丁香婷婷 | youjizz国产在线观看 | 97超碰精品成人国产 | AV导航第一福利网 | 收集最新中文国产中文字幕 | 日本无码人妻丰满熟妇A片 玩弄放荡人妇系列AV在线网站 | 无码人妻一区二区三区免费N鬼逝 | 日本japanese超丰满 | 精品人妻人人做人人爽 | 欧美经典一区二区三区 | 美女黄网站18禁免费看胸罩 | 啊灬啊灬啊灬快灬高潮了听书 |