simiar代码也出现在这里:list_entry in Linux
但我的问题是为什么要把它投到unsigned long
?因为根据C99 6.3.2.3,行为是未定义的或实现定义为将指针强制转换为整数
6.3.2.3: 6.任何指针类型都可以转换为整数类型。除非事先指明,否则 结果是实现定义的。如果结果无法以整数类型表示, 行为未定义。结果不必在任何整数的值范围内 类型。
那么为什么以前的内核会将指针强制转换为unsigned long?这是一个错误吗?
代码:
#include <stdio.h>
struct foobar{
unsigned int foo;
}tmp;
printf("\taddress and offset of tmp->foo= %p\n",
(struct foobar *)(((char *)&tmp.foo)
- ((unsigned long)&((struct foobar *)0)->foo)));
我使用gcc和x86_64机器,我知道这个代码tutorial
答案 0 :(得分:0)
此代码在Linux内核中实现container_of
宏。
正式适用于Linux内核的唯一编译器是gcc
,并且它具有与所有支持平台上的指针大小相同的unsigned long
类型。 (例如,对于64位平台gcc
遵循LP64类型模型,它具有64位long
)。
因此,从指针到unsigned long
并返回的转换在所有这些平台上都有效。
Linux内核中的现代container_of
implementation不会将unsigned long
用于指针算术,而是直接使用void*
- 这是另一个C extension GCC。