这个问题与C语言概念有关。
现有结构:
struct parent{
char c[4];
float f;
double d;
int flag;
struct child_old
{
int i;
float l;
}c1;
}
我想在父级下添加一个新结构(让我们调用它 - child_new)。 我根据场景一次只使用一个子结构。不是一次两个。 所以我可以将它们放在UNION下。
修改结构:
struct parent{
char c[4];
float f;
double d;
int flag;
union{
struct child_old
{
int i;
float j;
}c1;
struct child_new
{
int i;
float j;
char c[32];
double d;
}c2;
}UU;
}
这里我的要求是,基于struct member“flag”值(0/1),我需要决定我需要使用哪个子结构。
这是因为:
C可以吗? 或者有解决方案吗?
答案 0 :(得分:4)
你所写的内容很好,你会用以下内容来消费它:
switch(p.flag) {
case CHILD_OLD:
// work with p.c1
break;
case CHILD_NEW:
// work with p.c2
break;
}
但是,对于联盟中最大的成员,您的完整结构总是足够大。所以当你使用c1时,你仍然有足够的空间来分配c2。但是,至少你每次都没有分配sizeof(c1) + sizeof(c2)
。
如果你真的想根据每个记录使用的变量分配更多或更少的空间,你需要在结构中放置一个指针,并为子元素动态分配一个单独的记录。
所有这些都意味着,如果您从磁盘读取字节数组,然后将它们转换为结构:
parent *p = (parent*) addressOfSomeDataReadFromAFile;
(不是一个好主意,但在野外并不罕见)
...然后使用union技术扩展parent
结构通常不起作用。您的现有文件将表示记录的字节数少于新结构。
答案 1 :(得分:1)
鉴于您的要求
- 在使用child_old时,我不想消耗child_new所需的额外空间。
醇>
你不能使用工会。
Per 6.7.2.1结构和联合说明符,the C Standard第16段:
联合的大小足以包含其中最大的一个 成员。
因此,联盟的大小将是最大成员的大小。
另请注意,正如评论中所指出的,更改联合也可能会影响包含该联合的任何结构的其他元素的填充/对齐。
答案 2 :(得分:0)
这是可能的,但它既不漂亮也不有效。使用联合存储不同类型的无关数据被认为是不好的做法。正如已经提到的那样,大小将是联盟中最大的成员,因此它也不具有内存效率。
相反,这是一个更明智的解决方案:
struct parent {
char c[4];
float f;
double d;
int flag;
void* data;
}
...
struct parent x;
x.data = malloc(sizeof(struct child_old));
struct child_old* co_ptr = x.data;
co_ptr->i = ...;
这里void*
指向在别处分配的实际数据。您还需要一些方法来跟踪存储在那里的数据类型。
答案 3 :(得分:0)
它很难看但它有效。
#include <sys/stat.h>
#include <fcntl.h>
enum Type {
A,
B,
};
struct Base {
enum Type type;
};
struct A {
char foo[4];
};
struct B {
char bar[8];
};
struct BaseA {
struct Base base;
struct A a;
};
struct BaseB {
struct Base base;
struct B b;
};
int main(void) {
int fd = open("foo.bar", O_RDONLY);
if (fd == -1) {
return 1;
}
union {
struct Base base;
struct BaseA base_a;
struct BaseB base_b;
} buffer;
if (read(fd, &buffer.base, sizeof buffer.base) != sizeof buffer.base) {
return 1;
}
if (buffer.base.type == A) {
if (read(fd, &buffer.base_a.a, sizeof buffer.base_a.a) !=
sizeof buffer.base_a.a) {
return 1;
}
} else if (buffer.base.type == B) {
if (read(fd, &buffer.base_b.b, sizeof buffer.base_b.b) !=
sizeof buffer.base_b.b) {
return 1;
}
} else {
return 1;
}
}
你可以在if语句中做你想做的事。在数组中添加每个Base_A
,在另一个数组中添加所有Base_B
。
如果您不想填充,请使用#pragma pack(n)
。