<strike id="5ntnv"><i id="5ntnv"><del id="5ntnv"></del></i></strike>
<strike id="5ntnv"></strike><ruby id="5ntnv"></ruby><del id="5ntnv"><dl id="5ntnv"><del id="5ntnv"></del></dl></del><strike id="5ntnv"><dl id="5ntnv"><del id="5ntnv"></del></dl></strike>
<strike id="5ntnv"></strike>
<strike id="5ntnv"></strike>
<span id="5ntnv"><dl id="5ntnv"></dl></span>
<strike id="5ntnv"><i id="5ntnv"><del id="5ntnv"></del></i></strike><th id="5ntnv"><noframes id="5ntnv"><span id="5ntnv"><dl id="5ntnv"><del id="5ntnv"></del></dl></span>
<span id="5ntnv"></span>
<strike id="5ntnv"><dl id="5ntnv"><del id="5ntnv"></del></dl></strike>
<strike id="5ntnv"><dl id="5ntnv"><del id="5ntnv"></del></dl></strike><strike id="5ntnv"><i id="5ntnv"></i></strike><span id="5ntnv"></span>
<strike id="5ntnv"></strike>
<strike id="5ntnv"></strike>
<th id="5ntnv"><noframes id="5ntnv">
<ruby id="5ntnv"></ruby>
<strike id="5ntnv"><dl id="5ntnv"></dl></strike>

貴州網站建設公司貴州網站建設公司

Linux下的Container

Linux下的Container_of

看內核代碼的時候看到了container_of宏,寫的真是挺巧妙的,直接起到了this指針的功能

#define container_of(ptr, TYPE, MEMBER)({    \    const typeof(((TYPE *)0)->MEMBER) *_mptr = (ptr); \    (TYPE*)((char*)_mptr - offsetof(TYPE, MEMBER));  \})

當時主要有兩個疑問:

  • 為什么要有個臨時變量_mptr?直接使用ptr不就可以了?
  • 為什么要給mptr強轉成char*?

寫了段代碼
Container_of的測試代碼:

#include <stdio.h>#define offsetof(TYPE, MEMBER)({ (size_t) &(((TYPE *)0)->MEMBER);})#define container_of(ptr, TYPE, MEMBER)({    \    const typeof(((TYPE *)0)->MEMBER) *_mptr = (ptr); \    (TYPE*)((char*)_mptr - offsetof(TYPE, MEMBER));  \})struct stA{     char a;    int b[3];    double c;};int main (void) {     struct stA A;    double* x = &(A.c);    printf("%p\n",&A);    printf("%p <-- %p\n", x, container_of(x, struct stA, c));    return 0; }

這份代碼輸出如下:
0x7fff5718ebd0
0x7fff5718ebe0 <-- 0x7fff5718ebd0

如果去掉_mptr前的(char),輸出則為:
0x7fff519e6bd0
0x7fff519e6be0 <-- 0x7fff519e6b60
因為C語言指針變量的差值是根據指針變量類型來計算的,_mptr是double類型(8字節),實際上的結果是8
offsetof(TYPE, MEMBER)),這樣計算地址當然會出錯。

而對于

const typeof(((TYPE *)0)->MEMBER) *_mptr = (ptr);

一句的解釋,參考了這篇文章的描述:
這句話主要作用是在編譯時,能夠讓編譯器檢查ptr的類型和MEMBER的類型是否匹配,如果不匹配則產生相應的告警。
例如,

#include <stdio.h>#define offsetof(TYPE, MEMBER)({ (size_t) &(((TYPE *)0)->MEMBER);})#define container_of(ptr, TYPE, MEMBER)({    \    const typeof(((TYPE *)0)->MEMBER) *_mptr = (ptr); \    (TYPE*)((char*)_mptr - offsetof(TYPE, MEMBER));  \})struct stA{     char a;    int b[3];    double c;};int main (void) {     struct stA A;    double* x = &(A.c);    printf("%p\n",&A);    printf("%p <-- %p\n", x, container_of(x, struct stA, a)); //這里把成員變量名錯寫成a    return 0; }

編譯器在編譯時會告警:

warning: incompatible pointer types initializing 'const typeof (((struct stA *)0)->a) *' (aka 'const char *') with an expression of type 'double *' [-Wincompatible-pointer-types]

如果改成這樣:

#define container_of(ptr, TYPE, MEMBER)({    \    (TYPE*)((char*)ptr - offsetof(TYPE, MEMBER));  \})

編譯直接通過,這類錯誤難以發現。

找了下博客園里有這么篇文章,對于實現細節已經講的挺詳細了。

作者:NumberSix
來源鏈接:https://www.cnblogs.com/numbersix/p/4304600.html

贊(5)
未經允許不得轉載:>貴州網站建設公司 » Linux下的Container
国产欧美精品