offsetof由於不是標準庫的函式,所以得查一下,在stddef.h中,搜尋一下編譯器的這個標頭檔案位置:
暴力一點,直接在根目錄下搜尋,find -name 「stddef.h」,找到了這個
/usr/lib/gcc/i586-suse-linux/
4.8/include/stddef.h
開啟看下檔案內容,找到offsetof
/* offset of member member in a struct of type type. */
#define offsetof(type, member) __builtin_offsetof (type, member)
#define offsetof(st, m) ((size_t)&(((st *)0)->m))
這個定義在c11標準下是非法的,0表示空,這裡對空指標進行解引用,顯然是有問題的。linux使用者老實用gcc的實現方式就ok。
gcc的標頭檔案注釋就是針對結構體,查詢該結構體的某個成員變數相對結構體偏移量,就是該成員前面還有多少位元組的其他成員儲存的內容。寫個**測試一下:
#include
#include
typedef
struct test
test;
intmain
(int argc,
char
*ar**)
編譯執行結果如下:
說到這裡可能都覺得,這個有啥用,我都知道這個結構體的成員變數了,我自己算出來不就完事了?
其實在應用層的開發中好像比較少用到這個東西,但是在linux核心開發和驅動開發中比較常用這個東西來通過某個成員變數獲取結構體的首位址,來實現一些其他的操作。比如linux核心使用offsetof()來實現container_of()
#define container_of(ptr, type, member) ()
這個巨集經常被用來通過結構體某個內嵌成員變數來獲得該成員變數外包結構體的指標,好利用該結構體指標做其他用途。
舉個栗子:
#include
#include
#include
#include
#define container_of(ptr, type, member) ()
typedef
struct test
test;
intmain
(int argc,
char
*ar**)
memset
(my_test,0,
sizeof
(test));
my_test->a =1;
my_test->b =2;
my_test->c =3;
my_test->d =4;
my_test->e =5;
int*ptr =
&my_test->b;
test *ret =
container_of
(ptr, test, b)
;printf
("ret->b = %d\n"
, ret->b)
;free
(my_test)
; my_test =
null
;return0;
}
編譯執行:
root@lyx:
~/share/test/c_offect# gcc offset.c
root@lyx:
~/share/test/c_offect# .
/a.out
ret->b =
2
細心的同學可能會發現,我的執行環境變了。沒關係,這個一部分是在公司的休息時間寫的,一部分是在家的pc上寫的,所以會有環境的細微變化,不影響。
通過上面這個例子,是不是就可以解決只知道某個結構體的成員變數,然後通過這個成員變數找到該結構體的指標,這一用法其實在核心中很常見,如一些鍊錶的操作。
說到這裡我突然想到乙個問題:乙個單鏈表,先有乙個指標指向其中乙個節點,怎麼獲得他的上乙個節點,或者有個指標指向該節點的某個成員變數,求上乙個節點,是不是可以用這種方法去做,這裡不展開去講了,改天有時間寫個**出來實操一遍。
offsetof巨集的原理以及作用
原理 虛擬乙個type型別的結構體變數,通過type.member的方式來訪問member成員,進而得到member成員相對於整個結構體首位址的偏移量。作用 為接下來的container of巨集的講解出現做鋪墊 offsetof巨集 define offsetof type,member int ...
C語言的關鍵字說明以及用法
ansi c一共只有32個關鍵字,9種 控制語句 程式書寫形式自由,區分大小寫。把 高階語言 的基本結構和語句與低階語言的實用性結合起來。c 語言可以像組合語言一樣對位 位元組和位址進行操作,而這三者是計算機最基本的工作單元。他們的樣子以及說明 auto 宣告自動變數 break 跳出當前迴圈 ca...
C語言巨集中 和 的用法以及巨集展開規則
之前也看過一些c語言巨集的使用,特別是對 t 以及 text 巨集的實現也比較感興趣,但是之前對 t,text巨集的實現也是一知半解,沒有徹底搞明白,週末在寫另外一篇部落格 時恰好又用到了巨集,所以想好好把這塊學習整理下。的作用是把乙個token 標記 變成乙個字串,也就是使用 把token包含起來...