我对C结构中的弹性长度数组有疑问(http://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html)。
typedef struct {
size_t N;
int elems[];
} A_t;
现在一般方法很明显,
A_t * a = malloc(sizeof(A_t) + sizeof(int) * N)
a->N = N;
....
现在,当尝试将内容合并到其他结构或基于堆栈的分配时,这似乎很尴尬。因此,对于N!=0
struct {
A_t a;
A_t b; /// !!!!!
double c; /// !!!!!
};
现在我认为应该可以通过定义另一种类型
来允许这样的用法typedef struct {
size_t N;
int elems[5];
} A_5_t;
struct {
A_5_t a;
A_5_t b;
double c; // should work here now.
} mystruct;
然后将其用作A_t
结构。调用函数void foo(A_t * arg1);
时,需要使用foo((A_t*) (&mystruct.b))
之类的函数。哪个 - 对我来说 - 似乎有点笨拙。因此,我想知道是否有更好的方法来做到这一点。我想知道是否可以以某种方式使用联合类型?
我问这个问题,因为灵活长度数组可以在结构中将数据整合在一起,因此可以使用单个命令复制结构,而不必担心深度和浅层副本等
答案 0 :(得分:1)
你有一个多层次的问题。
在这个例子中:
struct {
A_t b;
double c; /// fails
};
我会尝试:
struct {
double c;
A_t b;
};
始终将结构的变量部分放在末尾。注意,我不使用GCC,所以试试这个,它可能/也许可以工作。
为了跟进@wirrbel给出的要求,以下结构是 NOT 变量长度,但它确实定义并提供对可变长度整数数组的访问。
typedef struct {
size_t N;
int *(elems[]); // parens to ensure a pointer to an array
} A_t;
A_t *a = malloc //etc.
a->elems = malloc(sizeof(int) * N);
以这种方式,几个A_t
结构可以包含在更通用的结构中。
答案 1 :(得分:1)
不,通常您的两个struct
,A_t
和A_5_t
不可互换。原因是具有灵活数组的版本可以在elems
字段前面具有与具有固定字段长度的版本不同的填充。
您的编译器是否实现了不同的填充,您可以使用offsetof
宏进行测试。但即使您的特定编译器和平台的偏移量相同,如果您需要可移植代码,也最好不要依赖它。
答案 2 :(得分:0)
我现在已经弄清楚了(解决方案实际上已在上面提供的gnu文档中描述)。通过在结构声明之后附加数组声明,可以创建一个与“空”灵活数组直接相邻的连续内存范围。因此,b.A.elems[i]
引用与b.elems_[i]
相同的数据。
可能建议选择一个标识符,告诉您该数组的内存实际上属于该结构。至少那就是我如何使用它。
typedef struct {
size_t N;
double elems[];
} A_t;
typedef struct {
A_t a;
double elems_[4];
} B_t;
void foo(A_t * arg1) {
for (size_t i=0; i < arg1->N; ++i) {
printf("%f\n", arg1->elems[i]);
}
}
int main(int argc, char *argv[]) {
B_t b;
b.a.N = 4;
for (int i=0; i < 4; ++i) {
b.elems_[i] = 12.4;
}
foo(&b.a);
}