在 `app.h` 中:
struct application_t{
void (*run_application)(struct application_t*);
void (*stop_application)(struct application_t*);
}
struct application_t* create();
问题出现在我尝试“实现”这个
application_t
时。我倾向于定义另一个结构体:app.c
:struct tcp_application_impl_t{
void (*run_application)(struct application_t*);
void (*stop_application)(struct application_t*);
int client_fd;
int socket_fd;
}
struct application_t* create(){
struct tcp_application_impl_t * app_ptr = malloc(sizeof(struct tcp_application_impl_t));
//do init
return (struct application_t*) app_ptr;
}
所以,如果我按照以下方式使用它:
#include "app.h"
int main(){
struct application_t *app_ptr = create();
(app_ptr -> run_application)(app_ptr); //Is this behavior well-defined?
(app_ptr -> stop_application)(app_ptr); //Is this behavior well-defined?
}
我困惑的问题是,如果我调用
(app_ptr -> run_application)(app_ptr);
会不会产生未定义行为。
app_ptr 的“静态类型”是 struct application_t*
,但“动态类型”是 struct tcp_application_impl_t*
。根据 N1570 6.2.7(p1) 的规定,struct application_t
和 struct tcp_application_t
不兼容:
它们的成员之间应该存在一对一的对应关系,使得每一对相应的成员都声明了兼容的类型
在这种情况下,显然不符合上述要求。
请问您能提供一份标准文件,解释这种行为吗?
application_t
类型会更好。 - Jean-François Fabrestruct tcp_application_impl_t { application_t base; int client_fd, socket_fd; }
,如果有变量tcp_application_impl_t *p
,则在二进制级别上&p->base == p
。请注意,翻译过程中不能改变原文意思,也不要在结果中包含解释或其他内容。 - RbMmcreate()
中使用&app_ptr->base;
,并且使用void run_application(application_t* p) { tcp_application_impl_t*q = CONTAINING_RECORD(p, tcp_application_impl_t, base); ...}
,其中#define CONTAINING_RECORD(address, type, field) ((type *)( (PCHAR)(address) - (ULONG_PTR)(&((type *)0)->field)))
。 - RbMm