(1)
Linux内核中链表为双链表结构,并且与普通链表不一样,在Linux内核链表中,不是在链表结构中包含数据,而是在数据结构中包含链表节点。因此内核链表的遍历比普通链表更加复杂。因此Linux内核中有一个宏用于从链表中访问到真正需要的数据项。
#define list_entry(ptr, type, member) container_of(ptr, type, member)
container_of宏定义在[include/linux/kernel.h]中:
#define container_of(ptr, type, member) ({ \
const typeof( ((type*)0)->member) *_mptr = (ptr); \
(type*)( (char*)_mptr - offsetof(type, member) );})
offsetof宏定义在[include/linux/stddef.h]中:
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
这里使用的是一个利用编译器技术的小技巧,即先求得结构成员在结构中的偏移量,然后根据成员变量的地址反过来得出属主结构变量的地址。
其中还有一个技巧((type*)0)->member,它将0地址强制“转换”为type结构的指针,再访问到type结构中的member成员。
(2)
在C++类中,独立于class object之外的存取操作,在某个时候特别重要:当class设计者希望支持“没有class object存在”的情况时。程序方法的解决之道是很奇特地把0强制转型为一个class指针,因而提供出一个this指针实体:
( (Class*)0)->objectFunc();
objectFunc((Class*)0);