简体   繁体   English

灵活数组成员的静态初始化

[英]Static initialization of a flexible array member

I am trying to compile this piece of code and it's giving me error: static initialization of flexible array member. 我正在尝试编译这段代码,这给了我一个错误:灵活数组成员的静态初始化。 I know it is because I am initializing the id and timestamp to 0 but they are supposed to be assigned at runtime and the 0s are just a place holder till then 我知道这是因为我正在将idtimestamp初始化为0但是应该在运行时分配它们,而0s只是一个占位符,直到那时

#include <stdio.h>
#include <stdlib.h>

#include "input.h"

typedef struct Ticket {
    int id;
    long timestamp;
} Ticket;

typedef struct Categories {
    char name[20];
    char code[3];
    Ticket ticket[];
} Category;

void genereateTickets() {
    struct Ticket *ptr;
    int nTickets = getNumTickets();
    ptr = (struct Ticket *)malloc(nTickets * sizeof(struct Ticket));

    for (int i = 0; i < nTickets; i++) {
        (ptr+i)->id = rand() % nTickets;
        (ptr+i)->timestamp = 0;
    }
}

void initializeCategories() {
    Category category1 = { "Academic Registrar", "AR", 0, 0 };
    Category category2 = { "Financial Services", "FS", 0, 0 };
    Category category3 = { "IT Support", "IT", 0, 0 };
    Category category4 = { "Parking Police", "PP", 0, 0 };
    Category category5 = { "Coop Placement", "CP", 0, 0 };
}

You cannot initialize a flexible array member. 您不能初始化灵活的数组成员。 Per C 2018 6.7.2.1 18, in most situations, a flexible array member is ignored. 根据C 2018 6.7.2.1 18,在大多数情况下,将忽略灵活数组成员。 This is one of those situations: In initialization, it is as if the member does not exist. 这是以下情况之一:在初始化中,就好像该成员不存在。

Creating a structure with a flexible array member in a declaration statement can only create a structure with zero members in the array. 在声明语句中创建具有灵活数组成员的结构只能在数组中创建具有零成员的结构。 To create a structure with more members in the array, you should dynamically allocate space with malloc or a similar routine. 要创建在数组中具有更多成员的结构,应使用malloc或类似的例程动态分配空间。 Once you have allocated sufficient space, you may convert the pointer to a pointer to a Category and then assign (rather than initialize) values to its members, including elements of its flexible array member. 一旦分配了足够的空间,就可以将指针转换为指向Category的指针,然后为其成员分配(而不是初始化)值,包括其灵活数组成员的元素。

(Conceivably, there might be a horrible way to define a union containing a structure with a flexible array member in such a way that sufficient space is provided for elements of the array, by stuffing the union with a char array of the necessary size. You still could not initialize those elements, but you could assign to them. Do not do this.) (可以想象,有一种可怕的方法来定义一个包含具有可伸缩数组成员的结构的联合,这种方式是通过在联合中填充必要大小的char数组来为数组的元素提供足够的空间。您仍然无法初始化这些元素,但是您可以分配给它们。不要这样做。)

To set up some prototype Category objects, you could use: 要设置一些原型Category对象,可以使用:

static const Category category1 = {"Academic Registrar"};
static const Category category2 = {"Financial Services"};
static const Category category3 = {"IT Support", "IT"};
static const Category category4 = {"Parking Police", "PP"};
static const Category category5 = {"Coop Placement", "CP"};

Later, to create a Category with several Ticket elements, you could do: 稍后,要创建包含几个Ticket元素的Category ,您可以执行以下操作:

Category *C = malloc(sizeof *C + nTickets * sizeof(Ticket));
// Test C for NULL in case malloc failed.

// Copy initial data into new Category.
*C = category3;

// Assign values to Ticket elements.
for (int i = 0; i < nTickets; ++i)
{
    C->ticket[i] = rand();
    C->timestamp = 0;
}

Note that you cannot create an array of Category objects, because they have flexible size, and objects in an array can only have a fixed size. 请注意,您无法创建Category对象的数组,因为它们的大小灵活,并且数组中的对象只能具有固定的大小。 So you can only work with one Category at a time. 因此,您一次只能使用一个Category The C pointer above can only point to one Category , not an array of them. 上面的C指针只能指向一个Category ,而不是它们的数组。 But the C->ticket member is an array of Ticket . 但是C->ticket成员是Ticket的数组。

Note that I do not necessarily recommend copying data into a Category from prototypes that way. 请注意,我不一定建议以这种方式将数据从原型复制到Category If the data is short, it could just be assigned in code. 如果数据较短,则可以仅通过代码分配。 If the data is long, it might be better to use pointers to data instead of copying all the data into each one. 如果数据很长,最好使用指向数据的指针,而不是将所有数据复制到每个数据中。 Good solutions depend on circumstances. 好的解决方案取决于情况。 The above code is given just as an example. 上面的代码仅作为示例给出。

For const structures of static duration, a workable approach in most cases is to declare a structure which has the same members as the FAM version, but with the flexible array member replaced by a suitably-sized array, and then construct a union which contains that type as well as the one with the Flexible Array Member. 对于静态持续时间的const结构,在大多数情况下,一种可行的方法是声明一个结构,该结构的成员与FAM版本的成员相同,但是将灵活数组成员替换为适当大小的数组,然后构造一个包含该成员的联合类型以及具有灵活数组成员的类型。 The Common Initial Sequence guarantees imply that either type may be used to inspect the common members, and if an implementation gives any heed whatsoever to footnote 88 of the C11 draft (N1570) which says the purpose of 6.5p7 is to specify the circumstance when things may alias, it will refrain from using the rule as an excuse to break such code, since references to storage that is never modified never alias (aliasing involves situations where re-ordering accesses to an object would affect the semantics thereof; if an object is never modified, the order of accesses will never have any observable effect). 通用初始序列保证暗示可以使用这两种类型来检查通用成员,并且如果实现对C11草案(N1570)的脚注88有任何注意,则6.5p7的目的是指定情况可能是别名,它将避免使用该规则作为破坏此类代码的借口,因为对永不修改的存储的引用永远不会别名(别名涉及以下情况:对对象的重新排序访问会影响其语义;如果对象是永远不会修改,访问顺序永远不会有任何可观察到的效果)。

In theory, an implementation would be allowed to place a flexible array member at a different offset from a fixed-sized array, but code could, if desired, use a static assertion to ensure that does not happen. 从理论上讲,将允许将一个灵活的数组成员放置在与固定大小的数组不同的偏移量处,但是如果需要,代码可以使用静态断言来确保不会发生这种情况。 A deliberately-obtuse interpretation might break things, but since the One Program Rule would allow deliberately-obtuse implementations to break just about any program, that's not really saying much. 故意混淆的解释可能会破坏事情,但是由于“一个程序规则”将允许故意混淆的实现破坏几乎任何程序,因此并没有说太多。

This code betrays a few misunderstandings about C. Here's what I assume to be a corrected version, with edits for spelling and style: 这段代码背叛了一些有关C的误解。以下是我认为是经过更正的版本,其中包含拼写和样式的修改:

#include <stdio.h>
#include <stdlib.h>

#include "input.h"

typedef struct Ticket {
  int id;
  long timestamp;
} Ticket;

typedef struct Categories {
  char name[20];
  char code[3];
  // One ticket doesn't need an array.
  Ticket ticket;
} Category;

void generateTickets(){
  struct Ticket *ptr;
  int nTickets = getNumTickets();
  ptr = malloc(nTickets * sizeof(struct Ticket));

  for(int i = 0; i < nTickets; i++)
  {
    // rand() % nTickets won't guarantee uniqueness
    ptr[i].id = rand() % nTickets;
    ptr[i].timestamp = 0;
  }
}

void initializeCategories() {
  // Nested initialisation for nested structs.
  Category category1 = {"Academic Registrar", "AR", {0, 0}};
  Category category2 = {"Financial Services", "FS", {0, 0}};
  Category category3 = {"IT Support", "IT", {0, 0}};
  Category category4 = {"Parking Police", "PP", {0, 0}};
  Category category5 = {"Coop Placement", "CP", {0, 0}};
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM