假设我们有一个
的实例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中的东西,如此处所示的类型部分重叠?
答案 0 :(得分:2)
你可以使用匿名结构/联合来伪装这个。自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;
};
};
答案 1 :(得分:1)
不确定“安全转弯”是什么意思,但我希望答案是“不”。结构是不同的,当然,较小的结构不能神奇地扩展到以前没有使用的内存中。
C中没有“重叠类型”的概念。
当然,你可以用CoreMessage
来声明Message
,但除了通过简化共享信息的传输之外,它对从较小类型到较大类型的反向转换没有帮助:
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;
这里没有什么是自动的,你必须自己做。
答案 2 :(得分:1)
不,你不能按照你的要求去做。但是,如果你愿意改变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
并非偶然。如果你不这样做,安排相应的布局要困难得多,第一个选择的指针值等价取决于它。
答案 3 :(得分:0)
我不确定“转入”究竟是什么意思。我不确定你怎么能为你做这个。
但是,C标准允许编译器在结构的字段之间放置未使用的空间,因此通常没有什么能真正起作用。你可以让“CoreMessage”包含一个“消息”并通过一次分配产生你的结果。