首页 文章

如何使用灵活的数组成员初始化结构

提问于
浏览
17

我有以下结构

typedef struct _person {
    int age;
    char sex;
    char name[];
}person;

关于如何创建实例并使用灵活的数组成员初始化结构而不使用 malloc() ,我已经完成了一些基本的互联网搜索(但不成功) .

例如:对于普通结构,如

struct a {
    int age; 
    int sex;
};

我们可以创建 struct a 的实例并将其初始化为

struct a p1 = {10, 'm'};

但对于具有灵活数组的结构(如上所述的 _person ),我们如何创建一个实例并初始化,就像我们为普通 structures 做的那样?

它甚至可能吗?如果是这样,我们如何在初始化期间传递数组大小以及要初始化的实际值?

(要么)

是否真的是使用灵活数组创建结构的唯一方法是使用C99规范中提到的 malloc() - 6.7.2.1 Structure and union specifiers - point #17

3 回答

  • 4

    你可以使用一些技巧 . 这取决于您的特定应用 .

    如果要初始化单个变量,可以定义正确大小的结构:

    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");
    

    另一个问题是这个技巧不适合创建一个"person"数组 . 数组的问题是所有元素必须具有相同的大小 . 在这种情况下,使用 const char * 而不是 char[] 会更安全 . 或者使用动态分配;)

  • 2

    不,必须始终手动分配灵活数组 . 但是您可以使用 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 的返回 . 在我编程到目前为止的所有系统中,这将相对较好地中止 . 一般来说,我认为return of malloc is of minor importance,但意见在很大程度上取决于该主题 .

    这可能(在那种特殊情况下)为优化器提供了更多机会来将代码集成到周围环境中:

    #define ALLOC_PERSON(A,  S,  N)                                 \
    ((person*)memcpy(calloc(sizeof(person) + (N), 1),               \
                     &(person const){ .age = (A), .sex = (S) },     \
                     sizeof(person)))
    

    Edit: 这可能比函数更好的情况是 AS 是编译时常量 . 在这种情况下,复合文字,因为它是 const 限定的,可以静态分配,并且它的初始化可以在编译时完成 . 此外,如果代码中出现几个具有相同值的分配,则允许编译器仅实现该复合文字的一个副本 .

  • 8

    具有柔性阵列成员的结构类型可以被视为省略了柔性阵列成员,因此您可以像这样初始化结构 .

    person p = { 10, 'x' };
    

    但是,没有分配灵活数组的成员,并且任何尝试访问灵活数组的成员或形成指向超出其末尾的成员的指针都是无效的 . 创建具有灵活数组成员的结构实例的唯一方法是为此动态分配内存,例如使用 malloc .

相关问题