C++ 中嵌套 C 结构的 offsetof()

Posted

技术标签:

【中文标题】C++ 中嵌套 C 结构的 offsetof()【英文标题】:offsetof() of nested C struct in C++ 【发布时间】:2012-07-26 07:10:45 【问题描述】:

我正在尝试将一个套接字过滤器添加到我在 C++ (Linux) 中的一个套接字中。在套接字过滤器中,我需要获取嵌套在另一个结构中的 struct fork_proc_event 的偏移量。定义如下(cn_proc.h):

struct proc_event 
    ...
    联合
        ...
        结构 fork_proc_event 
            __kernel_pid_t parent_pid;
            ...
         叉;
        ...
     事件数据;
    ...
;

在 C 中我会这样做:

int off = offsetof(struct fork_proc_event, parent_pid);

但是我正在使用 C++ 进行开发。如果我尝试这样做:

int off = offsetof(proc_event::fork_proc_event, parent_pid);

我收到以下错误:

错误:预期的类型说明符
错误:预期的“,”
错误:在 ',' 标记之前应为 `)'

offsetof() 行应该是什么样子的?

【问题讨论】:

只看一眼:会不会是proc_event::fork::fork_proc_event 不,它不起作用。我已经试过了。还是谢谢。 也许:offsetof(struct proc_event, event_data.fork.parent_pid) - offsetof(struct proc_event, event_data.fork) 【参考方案1】:

想一想offsetof 宏的实现方式可能会有所帮助。这是一个例子:

#define offsetof(TYPE, MEMBER) \
    ((uintptr_t)&(((TYPE*)0)->MEMBER))

换句话说,使用0作为指向您感兴趣的类型的指针,并简单地获取结构字段的地址...

因此,如果您想要 parent_pid 相对于 fork 的偏移量(这是我最初解析您的问题的方式):

((char*)&((struct proc_event*)0)->event_data.fork.parent_pid) - ((char*)&((struct proc_event*)0)->event_data.fork)

在第二次阅读时,您可能只想要parent_pid 相对于struct proc_event 开头的偏移量。改编上面的例子是:

((uintptr_t)&((struct proc_event*)0)->event_data.fork.parent_pid)

【讨论】:

谢谢,但是:错误:“struct proc_event”没有名为“fork”的成员 @VíctorFernández - 是的,我最初没有注意到event_data。请刷新。我也在用其他东西编辑答案。 指针大小(除了某些函数指针)是相同的。将指针转换为 char* 或 uintptr_t 而无需取消引用它只会使代码更难阅读 IMO。这是有原因的吗? @fish - 我转换为char * 以使减法以字节为单位工作,而不是以所采用的指针类型为单位。 (如果没有强制转换,减法甚至不会有与操作数相同的指针类型,这太疯狂了!)我强制转换为uintptr_t,因为&foo->member 是指针类型而不是整数 - 同样,当你正在寻找偏移,没有这个演员是不理智的。 @fish:转换为char * 意味着您可以可靠地计算结构成员的偏移量。如果没有强制转换,您将对错误的类型执行指针运算并得到错误的结果。【参考方案2】:

我并不完全理解所有这些 hack 的必要性,因为您所要做的就是为嵌套的 union 类型命名。任何名称,只是为了能够在 C++ 代码中引用它

struct proc_event 
    ...
    union whatever 
        ...
        struct fork_proc_event 
            __kernel_pid_t parent_pid;
            ...
         fork;
        ...
     event_data;
    ...
;

然后你就可以在 C++ 代码中将它称为proc_event::whatever::fork_proc_event in offsetof

size_t off = offsetof(proc_event::whatever::fork_proc_event, parent_pid);

如果您对parent_pidproc_event 开头的偏移量感兴趣,您可以这样做

size_t off = offsetof(proc_event, event_data.fork.parent_pid);

如果不能更改声明,可以通过做计​​算parent_pidfork_proc_event内的偏移量

size_t off = 
  offsetof(proc_event, event_data.fork.parent_pid) - 
  offsetof(proc_event, event_data.fork);

(虽然我不能马上说最后两个是否是offsetof使用的正式合法示例,但它们在实践中通常可以正常工作。)

【讨论】:

@Víctor Fernández:我也在回答中提到了这个案例。

以上是关于C++ 中嵌套 C 结构的 offsetof()的主要内容,如果未能解决你的问题,请参考以下文章

C语言 泛型链表 如何计算(结构体中各元素)相对内存地址?(字节对齐,结构体对齐)offsetof()函数 & ( (struct X*)0 ) -> Y)语法

offsetof

在嵌套匿名结构上忽略 C++ 私有修饰符

container_of 和 offsetof宏

offsetof与container_of宏分析

python 和 ctypes 访问具有嵌套结构的 c++ 类