简体   繁体   中英

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

#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. 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. 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.

(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.)

To set up some prototype Category objects, you could use:

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:

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. So you can only work with one Category at a time. The C pointer above can only point to one Category , not an array of them. But the C->ticket member is an array of Ticket .

Note that I do not necessarily recommend copying data into a Category from prototypes that way. 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. 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).

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:

#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}};
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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