如何使用灵活的数组成员初始化结构
我有以下结构
typedef struct _person { int age; char sex; char name[]; }person;
关于如何创建实例并使用灵活的数组成员初始化结构而不使用malloc()
我已经完成了一些基本的互联网搜索(但不成功malloc()
。
例如:对于普通结构,如
struct a { int age; int sex; };
我们可以创建一个struct a
的实例并将其初始化为
struct a p1 = {10, 'm'};
但是对于具有灵活数组的结构(如_person
提到的_person
),我们如何创建一个实例并初始化,就像我们如何为普通structures
做的那样?
它甚至可能吗? 如果是这样,我们如何在初始化期间传递数组大小以及要初始化的实际值?
(要么)
是否真的是使用灵活数组创建结构的唯一方法是使用C99规范中提到的malloc()
– 6.7.2.1 Structure and union specifiers - point #17
?
不,必须始终手动分配灵活数组。 但是您可以使用calloc
初始化灵活部分和复合文字来初始化固定部分。 我将它包装在一个分配inline
函数中,如下所示:
typedef struct person { unsigned age; char sex; size_t size; char name[]; } person; inline person* alloc_person(int a, char s, size_t n) { person * ret = calloc(sizeof(person) + n, 1); if (ret) memcpy(ret, &(person const){ .age = a, .sex = s, .size = n}, sizeof(person)); return ret; }
注意,如果分配成功,则检查是否成功。
如果你不需要像我在这里包含它的size
字段,宏甚至就足够了。 只有在执行memcpy
之前无法检查calloc
的返回。 在我编程到目前为止的所有系统中,这将相对较好地中止。 一般来说,我认为malloc
回归不太重要 ,但意见在很大程度上取决于该主题。
这可能(在那种特殊情况下)为优化器提供了更多机会来将代码集成到周围环境中:
#define ALLOC_PERSON(A, S, N) \ ((person*)memcpy(calloc(sizeof(person) + (N), 1), \ &(person const){ .age = (A), .sex = (S) }, \ sizeof(person)))
编辑:当A
和S
是编译时常量时,这可能比函数更好的情况。 在这种情况下,复合文字,因为它是const
限定的,可以静态分配,并且它的初始化可以在编译时完成。 此外,如果代码中出现几个具有相同值的分配,则允许编译器仅实现该复合文字的一个副本。
你可以使用一些技巧。 这取决于您的特定应用。
如果要初始化单个变量,可以定义正确大小的结构:
struct { int age; char sex; char name[sizeof("THE_NAME")]; } your_variable = { 55, 'M', "THE_NAME" };
问题是你必须使用指针转换将变量解释为“person”(例如“*(person *)(&your_variable)”。但你可以使用包含联合来避免这种情况:
union { struct { ..., char name[sizeof("THE_NAME")]; } x; person p; } your_var = { 55, 'M', "THE_NAME" };
所以,your_var.p的类型为“person”。 您也可以使用宏来定义初始化程序,因此您只能编写一次字符串:
#define INIVAR(x_, age_, sex_ ,s_) \ union {\ struct { ..., char name[sizeof(s_)]; } x;\ person p;\ } x_ = { (age_), (sex_), (s_) } INIVAR(your_var, 55, 'M', "THE NAME");
另一个问题是这个技巧不适合创建一个“人”arrays。 数组的问题是所有元素必须具有相同的大小。 在这种情况下,使用const char *
而不是char[]
更安全。 或者使用动态分配;)
具有柔性arrays成员的结构类型可以被视为省略了柔性arrays成员,因此您可以像这样初始化结构。
person p = { 10, 'x' };
但是,没有分配灵活数组的成员,并且任何尝试访问灵活数组的成员或形成指向超出其末尾的成员的指针都是无效的。 创建具有灵活数组成员的结构实例的唯一方法是在该数组中实际拥有元素,例如使用malloc
为其动态分配内存。