具有N个字段的类型A是否可以将其合并到具有N + x个字段的类型B的新对象中?

时间:2015-04-15 14:52:59

标签: c struct

假设我们有一个

的实例
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中的东西,如此处所示的类型部分重叠?

4 个答案:

答案 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”包含一个“消息”并通过一次分配产生你的结果。