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_pid
与proc_event
开头的偏移量感兴趣,您可以这样做
size_t off = offsetof(proc_event, event_data.fork.parent_pid);
如果不能更改声明,可以通过做计算parent_pid
在fork_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)语法