使用另一个结构的内容初始化一个结构

时间:2017-02-10 06:18:22

标签: c struct initialization

我们说我有一个结构类型:

typedef struct
{
    int a;
    int b[3];
    int c;
} __attribute__((packed)) foo_t;

我这样初始化:

foo_t first = { 1, { 2, 3, 4 }, 5 };

现在我想创建第二个结构,它是第一个结构的一个子集:

typedef struct
{
    int b[3];
    int c;
} __attribute__((packed)) bar_t;

bar_t second = { first.b[3], first.c }; //this should define first.c as 5
memcpy(second.b, first.b, 3 * sizeof(int));

如果我在second中打印每个变量的值,则会正确定义数组b,但c只是0。

printf("%d %d %d %d\n", second.b[0], second.b[1], second.b[2], second.c);

输出

2 3 4 0

为什么没有second.c正确填充?

3 个答案:

答案 0 :(得分:0)

在发布此内容后几秒钟回答了我自己的问题。

为了使用数组初始化新结构的内容,必须在数组部分周围放置大括号。此外,将first.b[3]指定为初始化值实际上将获取3元素数组的第4个元素,这是未定义的和错误的代码。 {0}可用作任何任意大小的数组的占位符,直到下一行使用memcpy。因此,正确的代码段应如下所示:

typedef struct
{
    int b[3];
    int c;
}__attribute__((packed)) bar_t;

bar_t second = { {0}, first.c}; //this should define first.c as 5
memcpy(second.b,first.b,3*sizeof(int));

答案 1 :(得分:0)

关于代码维护,使用memcpy()将结构的某些部分复制到另一个不同类型的结构是有问题的:如果所涉及的结构类型中的一个(但不是两个)被修改会发生什么?

因此,我建议使用

typedef struct
{
    int b[3];
    int c;
} __attribute__ ((__packed__)) bar;

typedef struct
{
    int a;
    bar bar;
} __attribute__ ((__packed__)) foo;

然后,

foo  first = {1, {2, 3, 4}, 5};
bar  second;
你显然可以做到

second = foo.bar;

就个人而言,我也建议添加访问者宏:

#define BAR_B(var, index) ((var).b[index])
#define BAR_C(var)        ((var).c)

#define FOO_A(var)        ((var).a)
#define FOO_B(var, index) ((var).bar.b[index])
#define FOO_C(var)        ((var).bar.c)

可以用作左值和右值(即任务中的任一侧)。它使维护更容易,以防您以后需要重新拆分或重新排列结构内容;然后,您不需要更改代码本身,只需修改访问者宏。

答案 2 :(得分:0)

在您的定义中,first.c被解析为second.b的第二个条目的初始值设定项,它会被memcpy立即覆盖。顺便提一下,first.b[3]first.b之后的无效访问。

为了使用second.c的值初始化first.c,初始化程序应重写为:

bar_t second = { { 0 } , first.c};
memcpy(second.b, first.b, sizeof(second.b));

您还可以通过明确初始化memcpy元素来摆脱second.b

bar_t second = { { first.b[0], first.b[1], first.b[2] }, first.c};

另请注意,__attribute__((packed))在您的声明中不可移植且无用,因为所有类型都相同。除非绝对必要,否则请避免使用此类内容。