0

So I have these 2 structures:

typedef struct item { 
    const char *label;
    int value;
} Item;

typedef struct item_coll { 
    size_t length; 
    Item items[]; 
} ItemColl;

And I want to do this:

 int main() {

    Item a = {"A", 10};
    Item b = {"B", 20};
    Item c = {"C", 30};

    Item items[] = {a, b, c};

    size_t length = sizeof(items)/sizeof(items[0]);

    ItemColl *column = malloc (sizeof(column) + length * sizeof(Item));

    column -> length = length;
    column -> items = items;

    printf("%ld\n", column -> length);

    return 0;
}

But I'm getting the error "Invalid use of flexible array member" here:

column -> items = items;

As far as I know, I'm allocating the needed space, which is why I don't understand what the problem is.

I've seen 2 more posts with this title but none of them solves my problem, as I've tried the answers to those questions.

5
  • 2
    You cannot assign one array to another using = - flexible array member or otherwise Commented Jan 12, 2019 at 20:07
  • 2
    Aside: did you mean sizeof(*collumn)? You are getting the size of a pointer. Commented Jan 12, 2019 at 20:07
  • 2
    You either need a memcpy or for (int idx = 0; idx < length; ++idx) collumn->items[idx] = items[idx]; instead of collumn->items = items; Commented Jan 12, 2019 at 20:12
  • Thanks a lot @CraigEstey. That worked. Make an answer with that so I can mark it. Commented Jan 12, 2019 at 20:15
  • sizeof(collumn) is just the size of a pointer, you need to use sizeof *collumn instead. Commented Jan 14, 2019 at 7:29

1 Answer 1

1

As others have mentioned, you can't assign one array to another.

Partly, because the compiler can't always know how long the array is, particularly for a flexible array member. (e.g.) Also, either the source or target might be a pointer. To be consistent, it just flags it.

So, change:

column->items = items;

to:

for (int idx = 0;  idx < length;  ++idx)
    column->items[idx] = items[idx];

Or, to use memcpy:

memcpy(column->items, items, sizeof(column->items[0]) * length);

Side note:

If column->items were a pointer (e.g. Item *items) instead, doing:

column->items = items;

would be valid. But, it would not copy the values. It would just set the struct's pointer to the address of the function scoped array items. This would not be the desired result.

Sign up to request clarification or add additional context in comments.

2 Comments

@miquelini don't forget to correct the sizeof error.
memcpy(collumn->items,items,sizeof collumn->items[0] * length); has an advantage over memcpy(...,...,sizeof(Item) ...);, it is easier to reivew and remains correct should the type of .items change.