您好,登錄后才能下訂單哦!
這兩個是在linux內核中經常用到的兩個宏,先說offsetof這個宏的作用就是來計算在結構體中的一個元素與結構體地址的偏移量。結構體的元素訪問其實就是指針訪問,直接應用的時候是用一個點來訪問的但是其實在底層經過編譯器編譯后的執行程序還是用這個偏移量的地址來訪問的例如定義一個結構體如下
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;
}
這種用點的形式直接訪問其本質是如下的:
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);
這樣得到結構是完全正確的意思就是這個偏移量很重要,所有就產生了offsetof這個宏,他的原型是
#define offsetof(Type,Member) ((int)&((Type*)0)->Member)
首先有兩個參數Type是指這個結構體的類型名,member就是這個結構體的成員名經過這個宏之后就返回了一個×××數是這個成員變量在這個結構體中相對于結構體地址的偏移量這里邊有一個(Type*)0)最不好理解意思就是假設了一個type類型的結構體他的地址是在地址0處其實這個結構體是不存在的但是這樣假定使用是不會有問題的,因你又沒有引用這個地址所有就沒有問題了,其實返回的這個數就是這個成員的地址減去結構體的地址但是因為結構體的地址是0所有就能直接返回這個成員的地址而也正因為結構體的地址是零所有成員的地址也就正好是偏移量了。
而container_of這個宏就是在offsetof這個宏的基礎上發展來的他的作用就是知道一個結構體中的成員的地址通過這個宏的運算后得到了結構體的地址,這個就厲害了因為你只要知道了結構體的指針那么你就可以得到結構體中的任何一個元素。這個宏的源型是#define container_of(ptr,type,member) ({\
Const typeof(((type)0)->member) mptr = (ptr);\
(type)((char)mptr - offsetof(type,member));})
有三個參數ptr是結構體中元素的指針,type是結構體的類型名,member是這個ptr指針的結構體元素名。這個宏里第一條我覺得其實也沒什么用去掉應該也可以因為他只是得到了這個結構體中成員變量的類型,之后這個成員變量的地址減去他在結構體中的偏移量那得到的就是結構體的指針在將類型強制轉換為結構體指針就可以了。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。