C語言巨集函式container of 簡介

2022-09-21 08:27:09 字數 1954 閱讀 7116

在linux 核心程式設計中,會經常見到乙個巨集函式container_of(ptr,type,member), 但是當你通過追蹤原始碼時,像我們這樣的一般人就會絕望了(這一堆都是什麼呀? 函式還可以這樣定義??? 怎麼還有0呢??? 哎,算了,還是放棄吧。。。)。 這就是核心大佬們厲害的地方,隨便兩行**就讓我們懷疑人生,凡是都需要乙個過程,慢慢來吧。

其實,原理很簡單: 已知結構體type的成員member的位址ptr,求解結構體type的起始位址。

type的起始位址 = ptr - size(這裡需要都轉換為char *,因為它為單位位元組)。

到此,該函式已經講完程式設計客棧,是不是很簡單??? 其實也不是,這裡並沒有提到size如何計算,而令我們頭暈的正是這裡。

好吧,先上container of函式原型:

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

其次為 offserof 函式原型:

#define offsetof(type, member) ((size_t) &((type *)0)->member)

怎麼樣,是不是很炫? 好吧,下面開始揭開面紗:

讓事實說話:

#include

struct test;

int main()

編譯執行,可以得到如下結果:

&temp = 0xbf9815b4

&temp.k = 0xbf9815bc

&((struct test *)0)->k = 8

什麼意思看到了吧,自定義的結構體有三個變數:i,j,k。 因為有位元組對齊要求,所以該結構體大小為4bytes * 3 =12 bytes. 而&((struct test *)0)->k 的作用就是求 k到結構體temp起始位址的位元組數大小(就是我們的size)。在這裡0被強制轉化為struct test *型, 它的作用就是作為指向該結構體起始位址的指標,就是作為指向該結構體起始位址的指標,就是作為指向該結構體起始位址的指標, 而&((struct test *)0)->k的作用便是求k到該起始指標的位元組數。。。其實是求相對位址,起始位址為0,則&k的值便是size大小(注:列印時因為需要整型,所以有個int強轉)所以我們便可以求我們需要的 size 了 。 好吧,一不小心把 offsetof() 函式的功能給講完了:::

#define offsetof(type, member) ((size_t) &((type *)0)->member)

這次再看就順眼了吧(底層為什麼是這樣我還是不懂。。。只知道這樣確實可以) , 所以offsetof()的作用就是求我們夢寐以求的size, 並以size_t形式返回(size_t: 無符號整型)。

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

這裡我們只看第二行:

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

它的作用是什麼呢? 其實沒什麼作用(勿噴勿噴,讓我把話說完),但就形式而言 _mptr = ptr, 那為什麼要要定義乙個一樣的變數呢??? 其實這正是核心人員的牛逼之處:程式設計客棧如果開發者使用時輸入的引數有問題:ptr與member型別不匹配,編譯時便會有warnning, 但是如果去掉改行,那個就沒有了,而這個警告恰恰是必須的(防止出錯有不知道錯誤在**)。。。這嚴謹性可以吧

typeof( ((type *)0)->member )

它的作用是獲取member的型別僅此而已。至此基本結束

container_of(ptr, type,member)函式的實現包括兩部分:

現在我們知道container_of()的作用就是通過乙個結構變數中乙個成員的位址找到這個結構體變數的首位址。

container_of(ptr,type,member),這裡面有ptr,type,member分別代表指標、型別、成員。

本文標題: c語言巨集函式container of()簡介

本文位址: /ruanjian/c/446521.html

C 語言 巨集定義和巨集函式

在軟體開發過程中,經常有一些常用或者通用的功能或者 段,這些功能既可以寫成函式,也可以封裝成為巨集定義。那麼究竟是用函式好,還是巨集定義好?這就要求我們對二者進行合理的取捨。我們來看乙個例子,比較兩個數或者表示式大小,首先我們把它寫成巨集定義 define max a,b a b a b 其次,把它...

C語言基礎 巨集函式

函式式巨集 巨集函式 和函式模擬會更加靈活,我們通過兩個例子來看一下。函式 include intsqr int int x double sqr double double x intmain int argc char ar 函式式巨集 include define sqr x x x intm...

C語言巨集定義和巨集定義函式

c語言巨集定義和巨集定義函式 巨集定義可以幫助我們防止出錯,提高 的可移植性和可讀性等。在軟體開發過程中,經常有一些常用或者通用的功能或者 段,這些功能既可以寫成函式,也可以封裝成為巨集定義。那麼究竟是用函式好,還是巨集定義好?這就要求我們對二者進行合理的取捨。我們來看乙個例子,比較兩個數或者表示式...