为什么在指针算术之前有一个转换为(char *)? (container_of()内部)

时间:2016-02-04 23:36:43

标签: c pointers casting linux-kernel macros

宏由

定义
#define container_of(ptr, type, member) ({                      \
        const typeof( ((type *)0)->member ) *__mptr = (ptr);    \
        (type *)( (char *)__mptr - offsetof(type,member) );})

我已经在这里查看了一些其他问题以及互联网上的其他一些资源,我很确定我理解这个宏是如何工作的。

我认为它的作用: 在第一行中,它创建一个新指针,该指针具有指向成员类型的指针类型,并为该指针指定给定指针的值。然后在第二行中,它使用offsetof来查找struct或union开头的地址。

我的问题是为什么这一行const typeof( ((type *)0)->member ) *__mptr = (ptr);在这里。似乎设置了正确的指针类型,然后立即转换为下一行中的char *

所以我的问题是为什么__mptr必须被强制转换为不同类型的指针?为什么不能将它保留为我设置它的任何类型然后从该指针中减去偏移量,因为我还是在减法之后再次投射它。此外,虽然我(想)我明白第一行正在做什么,但我不明白为什么它甚至是必要的。

为什么这样做比这更好:

#define container_of(ptr, type, member) ({                      \
            const typeof( ((type *)0)->member ) *__mptr = (ptr);    \
            (type *)(__mptr - offsetof(type,member) );})

或者

 #define container_of(ptr, type, member) ({                      \
             (type *)( (char *)ptr - offsetof(type,member) );})

1 个答案:

答案 0 :(得分:2)

因为否则减法会错误地将偏移量乘以ptr的大小。

也就是说,没有它,你会得到以下结果:

(type *)( (char *)__mptr - sizeof *__mptr * offsetof(type,member) );})