为什么以前的内核在 C 中投射指向无符号长整型的指针



simiar 代码也出现在这里: Linux 中的list_entry

但我的问题是,为什么要把它投给unsigned long?因为根据 C99 6.3.2.3,行为未定义或实现定义为强制转换指向 interger 的指针

6.3.2.3: 6. 任何指针类型都可以转换为整数类型。除非前面指定, 结果是实现定义的。如果结果无法以整数类型表示, 行为未定义。结果不必在任何整数的值范围内 类型。

那么为什么以前的内核会投射指向无符号长 long 的指针呢?这是一个错误吗?

代码:

#include <stdio.h>
struct foobar{
    unsigned int foo;
}tmp;
printf("taddress and offset of tmp->foo= %pn",
       (struct foobar *)(((char *)&tmp.foo)
               - ((unsigned long)&((struct foobar *)0)->foo)));     

我使用 gcc 和一台x86_64机器,我知道本教程中的代码

此代码在 Linux 内核中实现container_of宏。

唯一正式适合Linux内核的编译器是gcc,它unsigned long在所有支持的平台上都具有与指针相同的类型。(例如,对于 64 位平台gcc遵循 LP64 类型模型,该模型具有 64 位long(。

因此,从指针到unsigned long和返回的转换在所有这些平台上都是有效的。


Linux 内核中的现代container_of实现不使用unsigned long进行指针运算,而是直接使用 void* 进行操作 - 这是 gcc 的另一个 C 扩展。

最新更新