使用offsetof()获取指向成员不可知函数的成员的指针

时间:2017-10-29 21:22:05

标签: c struct casting pointer-to-member offsetof

假设我有struct喜欢:

typedef struct S S;
struct S {
    S *next;
    // ...
    S *gc_next;
};

即,它包含多个" next"指针同时在多个链表上。如果我想编写一个可以跟随任何" next"指针,我可以传递其中的"下一个"我想要的指针,例如:

void S_free_impl( S *p, size_t next_offset ) {
    while ( p ) {
        S *next = *PTR_OFFSET( p, S*, next_offset );
        free( p );
        p = next;
    }
}

其中PTR_OFFSET是一个宏,给定指向某个struct的指针,我想要的成员类型(在本例中为S*),以及成员的偏移量我想,然后取消引用该指针,我可以获得所需成员的值。

要获得偏移量,我可以编写一个前端宏来调用使用S_free_impl()的{​​{1}}:

offsetof

然后使用它:

#define S_FREE(PTR,NEXT)         S_free_impl( (PTR), offsetof( S, NEXT ) )

S_FREE( p, gc_next ); // free nodes following "gc_next" pointer 宏的初始实现可以是:

PTR_OFFSET

但是,如果您使用#define PTR_OFFSET(PTR,TYPE,OFFSET) \ (TYPE*)((char*)(PTR) + (OFFSET)) 进行编译,则会得到:

gcc -Wcast-align

抑制警告的一种方法是编写一种C语言的C ++等同于foo.c:21:24: warning: cast from 'char *' to 'S **' (aka 'struct S **') increases required alignment from 1 to 8 [-Wcast-align] S *next = *PTR_OFFSET( p, S*, next_offset ); ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

reinterpret_cast

然后重写#define REINTERPRET_CAST(T,EXPR) ((T)(uintptr_t)(EXPR)) 以使用它:

PTR_OFFSET

然后由于通过 #define PTR_OFFSET(PTR,TYPE,OFFSET) \ REINTERPRET_CAST( TYPE*, REINTERPRET_CAST( char*, (PTR) ) + (OFFSET) ) 投射警告而消失。

问题是:这是在C中获得我想要的最好(最便携)方式吗?具体做法是:

  1. 能够编写对不同uintptr_t成员(相同类型)进行操作的函数。
  2. 使用 struct返回的值的可移植方式,将其转换为指向成员的实际指针。

0 个答案:

没有答案