Flexible arrays getting in the way?

Discussion in 'C Programming' started by Andrea Taverna, Apr 3, 2009.

  1. 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
     
    Andrea Taverna, Apr 3, 2009
    #1
    1. Advertising

  2. Andrea Taverna <> writes:
    > 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.

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    Nokia
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
     
    Keith Thompson, Apr 3, 2009
    #2
    1. Advertising

  3. 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
     
    Andrea Taverna, Apr 3, 2009
    #3
  4. Andrea Taverna

    Old Wolf Guest

    On Apr 4, 10:19 am, Keith Thompson <> wrote:
    > Andrea Taverna <> writes:
    > > 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.


    Using the 'CLC idiom' for malloc avoids possible
    difficulties of getting the type right
    (i.e. sizeof *foo, instead of sizeof(slot*)).
     
    Old Wolf, Apr 5, 2009
    #4
  5. Andrea Taverna

    Eric Sosman Guest

    Old Wolf wrote:
    > On Apr 4, 10:19 am, Keith Thompson <> wrote:
    >> Andrea Taverna <> writes:
    >>> 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.

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

    --
    Eric Sosman
    lid
     
    Eric Sosman, Apr 5, 2009
    #5
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Olav
    Replies:
    1
    Views:
    348
    Steve C. Orr, MCSD
    Jul 31, 2003
  2. =?Utf-8?B?RGV2aW4=?=

    More flexible programs for the design of a page

    =?Utf-8?B?RGV2aW4=?=, Jun 1, 2004, in forum: ASP .Net
    Replies:
    8
    Views:
    323
    John Oakes
    Jun 1, 2004
  3. Sean Aitken
    Replies:
    1
    Views:
    291
  4. Flexible arrays - v confused

    , Feb 14, 2006, in forum: C Programming
    Replies:
    20
    Views:
    746
    Dave Thompson
    Feb 27, 2006
  5. Philipp
    Replies:
    21
    Views:
    1,190
    Philipp
    Jan 20, 2009
Loading...

Share This Page