具有 N 个字段的类型 A 是否可以将其合并到具有 N+x 个字段的类型 B 的新对象中?
Having type A with N fields is it possible to merge it into new object of type B with N+x fields?
假设我们有一个
的实例
struct Message {
char * topic;
int topicLength;
void * data;
int dataLength;
};
并且我们想将其重新创建为其他类型的对象
struct CoreMessage {
int messaageId;
char * topic;
int topicLength;
void * data;
int dataLength;
char * senderId;
int senderIdLength;
};
我们可以安全地将Message A
变成CoreMessage B
吗? C 中的东西没有复制内容,类型部分重叠,如此处所示?
不确定 "safely turn" 是什么意思,但我希望答案是 "no"。结构不同,当然不能指望较小的结构神奇地扩展到它以前没有使用过的内存中。
C中没有"overlapping types"的概念
你当然可以用Message
来声明CoreMessage
,但这对从较小类型到较大类型的反向转换没有任何帮助,除非传递共享信息更简单:
struct CoreMessage {
int messageId;
struct Message message;
char *senderId;
int senderIdLength;
};
现在如果我们有:
struct Message a = { ... }; /* fully initialized */
struct CoreMessage b; /* we want to convert Message into this */
我们可以做到:
b.messageId = 4711;
b.message = a; /* Copy all Message data over. */
b.senderId = "foo";
b.senderIdLength = 3;
这里没有什么是自动的,你必须自己做。
我不确定 "turn into" 是什么意思。我不确定你如何才能让演员为你做这件事。
但是,C 标准允许编译器将未使用的 space 放在结构的字段之间,因此,通常没有什么是真正有效的。您可以使 "CoreMessage" 包含一个 "Message" 并通过一次赋值产生您的结果。
不,你不能按照你的要求去做。但是,如果您愿意像这样更改 struct CoreMessage
的布局,您可以接近:
struct CoreMessage {
struct Message message;
int messaageId;
char * senderId;
int senderIdLength;
};
请注意 struct CoreMessage
然后包含一个实际的 struct Message
作为成员(而不是指向一个的指针)。然后,给出...
struct CoreMessage cm;
struct CoreMessage *cmp = &cm;
struct Message *mp = &cm.message;
...你有 (void *) cmp == (void *) mp
,这对你可能想做的某些事情很有用。这也会根据 struct Message
.
的更改自动调整
或者,您可以这样做:
struct Message {
char * topic;
int topicLength;
void * data;
int dataLength;
maximum_alignment_requirement_t resv1;
char resv2[AS_MANY_BYTES_AS_ANY_MESSAGE_TYPE_MAY_NEED_INCLUDING_PADDING];
};
struct CoreMessage {
char * topic;
int topicLength;
void * data;
int dataLength;
maximum_alignment_requirement_t resv1;
int messaageId;
char * senderId;
int senderIdLength;
};
struct Message msg;
struct CoreMessage *cmp = (struct CoreMessage *) &msg;
这很有可能会像您希望的那样工作(并且一些系统接口几乎就是这样工作的)但是 C 不保证那些相应的元素将被布置在两种不同的 struct
类型中采用相同的方式。
还要注意,我将 CoreMessage.messageId
移到与 struct Message
相对应的成员之后并非偶然。如果不这样做,很难安排相应的布局,第一个选择的指针值等价取决于它。
你可以用匿名 structures/unions 伪造这个。无可否认,自 C11
以来,匿名结构才被标准化,但许多流行的编译器长期以来一直支持它们作为扩展。
这就是这些,诚然不太漂亮,行:
struct Message {
char * topic;
int topicLength;
void * data;
int dataLength;
char * senderId;
int senderIdLength;
};
struct CoreMessage {
int messageId;
union {
struct Message;
struct Message message;
};
};
假设我们有一个
的实例struct Message {
char * topic;
int topicLength;
void * data;
int dataLength;
};
并且我们想将其重新创建为其他类型的对象
struct CoreMessage {
int messaageId;
char * topic;
int topicLength;
void * data;
int dataLength;
char * senderId;
int senderIdLength;
};
我们可以安全地将Message A
变成CoreMessage B
吗? C 中的东西没有复制内容,类型部分重叠,如此处所示?
不确定 "safely turn" 是什么意思,但我希望答案是 "no"。结构不同,当然不能指望较小的结构神奇地扩展到它以前没有使用过的内存中。
C中没有"overlapping types"的概念
你当然可以用Message
来声明CoreMessage
,但这对从较小类型到较大类型的反向转换没有任何帮助,除非传递共享信息更简单:
struct CoreMessage {
int messageId;
struct Message message;
char *senderId;
int senderIdLength;
};
现在如果我们有:
struct Message a = { ... }; /* fully initialized */
struct CoreMessage b; /* we want to convert Message into this */
我们可以做到:
b.messageId = 4711;
b.message = a; /* Copy all Message data over. */
b.senderId = "foo";
b.senderIdLength = 3;
这里没有什么是自动的,你必须自己做。
我不确定 "turn into" 是什么意思。我不确定你如何才能让演员为你做这件事。
但是,C 标准允许编译器将未使用的 space 放在结构的字段之间,因此,通常没有什么是真正有效的。您可以使 "CoreMessage" 包含一个 "Message" 并通过一次赋值产生您的结果。
不,你不能按照你的要求去做。但是,如果您愿意像这样更改 struct CoreMessage
的布局,您可以接近:
struct CoreMessage {
struct Message message;
int messaageId;
char * senderId;
int senderIdLength;
};
请注意 struct CoreMessage
然后包含一个实际的 struct Message
作为成员(而不是指向一个的指针)。然后,给出...
struct CoreMessage cm;
struct CoreMessage *cmp = &cm;
struct Message *mp = &cm.message;
...你有 (void *) cmp == (void *) mp
,这对你可能想做的某些事情很有用。这也会根据 struct Message
.
或者,您可以这样做:
struct Message {
char * topic;
int topicLength;
void * data;
int dataLength;
maximum_alignment_requirement_t resv1;
char resv2[AS_MANY_BYTES_AS_ANY_MESSAGE_TYPE_MAY_NEED_INCLUDING_PADDING];
};
struct CoreMessage {
char * topic;
int topicLength;
void * data;
int dataLength;
maximum_alignment_requirement_t resv1;
int messaageId;
char * senderId;
int senderIdLength;
};
struct Message msg;
struct CoreMessage *cmp = (struct CoreMessage *) &msg;
这很有可能会像您希望的那样工作(并且一些系统接口几乎就是这样工作的)但是 C 不保证那些相应的元素将被布置在两种不同的 struct
类型中采用相同的方式。
还要注意,我将 CoreMessage.messageId
移到与 struct Message
相对应的成员之后并非偶然。如果不这样做,很难安排相应的布局,第一个选择的指针值等价取决于它。
你可以用匿名 structures/unions 伪造这个。无可否认,自 C11
以来,匿名结构才被标准化,但许多流行的编译器长期以来一直支持它们作为扩展。
这就是这些,诚然不太漂亮,行:
struct Message {
char * topic;
int topicLength;
void * data;
int dataLength;
char * senderId;
int senderIdLength;
};
struct CoreMessage {
int messageId;
union {
struct Message;
struct Message message;
};
};