關於container_of函數分析


#include <stdio.h>

#define offset_of(type,member) ((int)&(((type *)0)->member))

#define container_of(ptr,type,member) ({\    
    const typeof(((type*)0)->member) *__mptr = ptr;\    
    (type *)((char *)__mptr - offset_of(type,member));\
    })

struct mytest{
    char i;
    int j;
    char *k;
    };
 int main(){
    struct mytest temp;
    struct mytest *p;
    printf("&temp = %p\n",&temp);   
    printf("&temp.k = %p\n",&temp.k);
    printf("&((struct mytest *)0)->k = %d\n",((int)&((struct mytest *)0)->k));
        printf("&temp = %p  \n",container_of(&temp.j,struct mytest,j));
        printf("&temp = %p  \n",container_of(&temp.k,struct mytest,k));
        return 0;}
View Code

(一).分析下宏定義1:

#define offset_of(type,member) ((int)&(((type *)0)->member))

     (type * )0 :強制把0地址轉化為type *類型

     &(((type *)0)->member) :將type類型的member成員的地址取出。這里用法很妙,由於type指針地址是0,故其成員地址都是基地址為0加上偏移地址。

     (int)(&(((type *)0)->member)) :將type成員類型地址強制轉化為int。

 

(二).分析下宏定義2:

#define container_of(ptr,type,member) ({\	
    const typeof(((type*)0)->member) *__mptr = ptr;\
    (type *)((char *)__mptr - offset_of(type,member));\
    })

       2.1. 分析 const typeof(((type *)0)->member) *__mptr = ptr;

                 const typeof(((type *)0)->member) :typeof是關鍵字,獲取成員類型。此部分是得到宏傳過來的成員類型。

                 const typeof(((type *)0)->member) *__mptr = ptr :此部分為什么要重新定義__mptr呢?這就是寫linux內核工程師的牛逼,嚴謹之處。如果開發者使                用時輸入的參數有問題:ptr與member類型不匹配,編譯時便會有warnning, 但是如果去掉改行,那個就沒有了,而這個警告恰恰是必須的(防止出錯有不              知道錯誤在哪里)。。。

       2.2. 分析(type *)((char *)__mptr - offset_of(type,member));

                (char *)__mptr :將成員類型強制轉化為char *,如此地址進行加減時以字節為單位

                (char *)__mptr - offset_of(type,member) :計算出結構體首地址,此時地址類型為char *

              (type *)((char *)__mptr - offset_of(type,member)):將char * 強制轉化為(type *)

 

索引文獻:https://blog.csdn.net/s2603898260/article/details/79371024

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM