Flexible arrays getting in the way?

A

Andrea Taverna

Hi folks.

I wrote the following piece of code

struct ht {
size_t count;
size_t size;
float load_treshold;
unsigned long (*hashf) (hash_item*);
boolean (*testf) (hash_item*, hash_item*);
unsigned long (*probef) (long, hash_item*, void*);
unsigned long (*newsizef) (void*);
slot* data[];
};

and compiled it with C99 standard.
I don't know the details of such standard but, apparently, the compiler thinks
that I'm trying to define a struct with a "flexible array data", with the result
that the following

struct ht foo;
foo->data = calloc(sizeof(slot)*some_size));

gets rejected as "invalid use of flexible array member".
As far as I understand, I should change code like that one into

struct ht* foo;
foo = malloc((sizeof(slot)*some_size)+ <size of other fields>);

Is it correct?
What should I do if I want to use a flexible array *without* "struct hacks"
*nor* C99 rules?
Should I switch to another standard?

TIA,

Andrea
 
K

Keith Thompson

Andrea Taverna said:
I wrote the following piece of code

struct ht {
size_t count;
size_t size;
float load_treshold;
unsigned long (*hashf) (hash_item*);
boolean (*testf) (hash_item*, hash_item*);
unsigned long (*probef) (long, hash_item*, void*);
unsigned long (*newsizef) (void*);
slot* data[];
};

and compiled it with C99 standard.
I don't know the details of such standard but, apparently, the
compiler thinks that I'm trying to define a struct with a "flexible
array data", with the result that the following

struct ht foo;
foo->data = calloc(sizeof(slot)*some_size));

gets rejected as "invalid use of flexible array member".

Right. foo->data is an array of pointers to slot, and you can't
assign to an array, whether it's a flexible array member or not.
As far as I understand, I should change code like that one into

struct ht* foo;
foo = malloc((sizeof(slot)*some_size)+ <size of other fields>);

Is it correct?

There's no good way to express <size of other fields>. Adding up the
sizes of the members is error-prone and ignores gaps. Just use:

foo = malloc(sizeof(struct ht) + COUNT * sizeof(slot*));

Note that I used sizeof(slot*), not sizeof(slot), since data is an
array of pointers, not an array of slots.
What should I do if I want to use a flexible array *without* "struct
hacks" *nor* C99 rules?
Should I switch to another standard?

C99 introduced flexible arrays to replace the struct hack, which was
of questionable portability. I'm not sure how you'd use it without
using either the struct hack or the C99 construct. Why do you want
to?

You could make the last member a single pointer and allocate the data
separately, but then the data isn't contiguous with the rest of your
structure and managing the allocation and deallocation becomes a bit
more tricky.
 
A

Andrea Taverna

Keith Thompson ha scritto:
Right. foo->data is an array of pointers to slot, and you can't
assign to an array, whether it's a flexible array member or not.
<shout>ZOMG!!1!
</shout>
*blush*
Sorry guys, It's been a tiring day. I missed the '*' next to data...

thanks again

Andrea
 
O

Old Wolf

There's no good way to express <size of other fields>.  Adding up the
sizes of the members is error-prone and ignores gaps.  Just use:

    foo = malloc(sizeof(struct ht) + COUNT * sizeof(slot*));

Note that I used sizeof(slot*), not sizeof(slot), since data is an
array of pointers, not an array of slots.

Using the 'CLC idiom' for malloc avoids possible
difficulties of getting the type right
(i.e. sizeof *foo, instead of sizeof(slot*)).
 
E

Eric Sosman

Old said:
Using the 'CLC idiom' for malloc avoids possible
difficulties of getting the type right
(i.e. sizeof *foo, instead of sizeof(slot*)).

... which would be wrong, since `foo' is a `struct ht*'
and not a `slot**'.

Restoring some snipped context, we've got

struct ht {
/* ... stuff ... */
slot* data[];
};
struct ht *foo;

.... so I think a suitable adaptation of "the CLC idiom"
for this case would be

foo = malloc(sizeof *foo + COUNT * sizeof foo->data[0]);

(Or write `sizeof *foo->data' if your taste so dictates.)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,012
Latest member
RoxanneDzm

Latest Threads

Top