为什么以前的内核在C中将指针指向unsigned long

时间:2018-04-05 14:48:46

标签: c kernel

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

1 个答案:

答案 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。