溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

offsetof與container_of宏的理解

發(fā)布時(shí)間:2020-07-13 14:37:25 來(lái)源:網(wǎng)絡(luò) 閱讀:318 作者:秋天的細(xì)語(yǔ) 欄目:編程語(yǔ)言

這兩個(gè)是在linux內(nèi)核中經(jīng)常用到的兩個(gè)宏,先說(shuō)offsetof這個(gè)宏的作用就是來(lái)計(jì)算在結(jié)構(gòu)體中的一個(gè)元素與結(jié)構(gòu)體地址的偏移量。結(jié)構(gòu)體的元素訪問(wèn)其實(shí)就是指針訪問(wèn),直接應(yīng)用的時(shí)候是用一個(gè)點(diǎn)來(lái)訪問(wèn)的但是其實(shí)在底層經(jīng)過(guò)編譯器編譯后的執(zhí)行程序還是用這個(gè)偏移量的地址來(lái)訪問(wèn)的例如定義一個(gè)結(jié)構(gòu)體如下
typedef struct test{
char t1;
int t2;
short t3;
}test;
int main(void)
{
test s1;
s1.t1='a';
s1.t2=123;
s1.t3=456;

return 0;

}
這種用點(diǎn)的形式直接訪問(wèn)其本質(zhì)是如下的:

test p;
char
p1;
int p2;
short
p3;
p=&s1;
p1=(char )((int)p+0)
p2=(int
)((int)p + 4);
p3=(short *)((int)p + 8);

printf("*p1 = %c.\n",*p1);
printf("*p2 = %d.\n",*p2);
printf("*p3 = %d.\n",*p3);
這樣得到結(jié)構(gòu)是完全正確的意思就是這個(gè)偏移量很重要,所有就產(chǎn)生了offsetof這個(gè)宏,他的原型是
#define offsetof(Type,Member)  ((int)&((Type*)0)->Member)
首先有兩個(gè)參數(shù)Type是指這個(gè)結(jié)構(gòu)體的類型名,member就是這個(gè)結(jié)構(gòu)體的成員名經(jīng)過(guò)這個(gè)宏之后就返回了一個(gè)×××數(shù)是這個(gè)成員變量在這個(gè)結(jié)構(gòu)體中相對(duì)于結(jié)構(gòu)體地址的偏移量這里邊有一個(gè)(Type*)0)最不好理解意思就是假設(shè)了一個(gè)type類型的結(jié)構(gòu)體他的地址是在地址0處其實(shí)這個(gè)結(jié)構(gòu)體是不存在的但是這樣假定使用是不會(huì)有問(wèn)題的,因你又沒(méi)有引用這個(gè)地址所有就沒(méi)有問(wèn)題了,其實(shí)返回的這個(gè)數(shù)就是這個(gè)成員的地址減去結(jié)構(gòu)體的地址但是因?yàn)榻Y(jié)構(gòu)體的地址是0所有就能直接返回這個(gè)成員的地址而也正因?yàn)榻Y(jié)構(gòu)體的地址是零所有成員的地址也就正好是偏移量了。
而container_of這個(gè)宏就是在offsetof這個(gè)宏的基礎(chǔ)上發(fā)展來(lái)的他的作用就是知道一個(gè)結(jié)構(gòu)體中的成員的地址通過(guò)這個(gè)宏的運(yùn)算后得到了結(jié)構(gòu)體的地址,這個(gè)就厲害了因?yàn)槟阒灰懒私Y(jié)構(gòu)體的指針那么你就可以得到結(jié)構(gòu)體中的任何一個(gè)元素。這個(gè)宏的源型是#define container_of(ptr,type,member)  ({\

Const typeof(((type)0)->member) mptr = (ptr);\
(type)((char)
mptr - offsetof(type,member));})

有三個(gè)參數(shù)ptr是結(jié)構(gòu)體中元素的指針,type是結(jié)構(gòu)體的類型名,member是這個(gè)ptr指針的結(jié)構(gòu)體元素名。這個(gè)宏里第一條我覺(jué)得其實(shí)也沒(méi)什么用去掉應(yīng)該也可以因?yàn)樗皇堑玫搅诉@個(gè)結(jié)構(gòu)體中成員變量的類型,之后這個(gè)成員變量的地址減去他在結(jié)構(gòu)體中的偏移量那得到的就是結(jié)構(gòu)體的指針在將類型強(qiáng)制轉(zhuǎn)換為結(jié)構(gòu)體指針就可以了。
向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI