#define container_of(ptr, type, member) ({ \
const typeof( ((type *)0)->member ) *__mptr = (ptr); \
(type *)( (char *)__mptr - offsetof(type,member) ); })
#define container_of_simple(ptr, type, member) \
(type *)( (char *)ptr - offsetof(type,member) )
看起來功能相同,但**忽略了副作用風險**。
`({ ... })` 是 GCC 擴展,允許在表達式位置寫入**復合語句**(含變量聲明、循環、控制流),整個塊的值為最後一條語句的值。
int x = ({ int a = 3; int b = 5; a + b; }); // x = 8
const typeof( ((type *)0)->member ) *__mptr = (ptr);
// 1. ((type *)0)->member : 以 0 地址為基址,訪問 member 偏移,類型為 member 的類型
// 2. typeof(...) : 獲取 member 的類型(如 int、struct ListHead* 等)
// 3. const ... *__mptr = (ptr) : 定義一個指向 member 類型的常量指針,賦值為 ptr
// → 關鍵:__mptr 是**臨時變量**,只求值一次,避免 ptr 為有副作用的表達式(如 func()、i++)被多次求值
(type *)( (char *)__mptr - offsetof(type,member) );
// 4. 將 __mptr 轉為 char*,減去 member 在 type 中的偏移量,得到 type 結構體起始地址
// 5. 強轉為 type*,作為整個語句表達式的值返回
// 危險場景:ptr 為函數調用
struct Node *p = container_of(get_node(), struct Node, list);
// 若用簡化版:
// (type *)((char *)get_node() - offsetof(...))
// get_node() 會被調用**兩次**!導致邏輯錯誤、性能損耗、甚至崩潰
// container_of 保證 get_node() 只調用一次,結果賦給 __mptr 復用
#define min(x, y) ({ \
typeof(x) _x = (x); \
typeof(y) _y = (y); \
(void)(&_x == &_y); /* 類型檢查 */ \
_x < _y ? _x : _y; })
// 防止 min(a++, b++) 導致 a/b 增加兩次