【问题标题】:offsetof() of nested C struct in C++C++ 中嵌套 C 结构的 offsetof()
【发布时间】: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)

标签: c++ c sockets struct offsetof


【解决方案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:我也在回答中提到了这个案例。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-12-11
  • 2014-10-12
  • 2021-04-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多