Static array with #defined # of "extra" members

Discussion in 'C Programming' started by Ian Pilcher, Aug 4, 2012.

  1. Ian Pilcher

    Ian Pilcher Guest

    I need to create a static array of structures with the following
    characteristics:

    * The first few members of the array are pre-initialized
    * The remaining members of the array are initialized to "zero"
    * The number of additional members is determined by a #defined constant,
    independently of the number of pre-initialized members

    Here's what I've come up with:


    #define NUM_EXTRA_FOOS 5

    struct foo {
    int data;
    };

    static struct {
    struct foo builtin[5];
    struct foo extra[NUM_EXTRA_FOOS];
    } all_foos = {
    { { 1 }, { 2 }, { 3 }, { 4 }, { 5 } },
    { { 0 } }
    };

    #define foos all_foos.builtin

    I believe that I can effectively use foos[] as an array with 10 (5 +
    NUM_EXTRA_FOOS) elements.

    * Is my belief correct?
    * Is there any danger of the compiler inserting unwanted padding between
    the builtin and extra members of the anonymous struct?
    * Is there a better way to do this?

    Thanks!

    --
    ========================================================================
    Ian Pilcher
    "If you're going to shift my paradigm ... at least buy me dinner first."
    ========================================================================
     
    Ian Pilcher, Aug 4, 2012
    #1
    1. Advertising

  2. Ian Pilcher

    Eric Sosman Guest

    On 8/3/2012 10:05 PM, Ian Pilcher wrote:
    > I need to create a static array of structures with the following
    > characteristics:
    >
    > * The first few members of the array are pre-initialized
    > * The remaining members of the array are initialized to "zero"
    > * The number of additional members is determined by a #defined constant,
    > independently of the number of pre-initialized members
    >
    > Here's what I've come up with:
    >
    >
    > #define NUM_EXTRA_FOOS 5
    >
    > struct foo {
    > int data;
    > };
    >
    > static struct {
    > struct foo builtin[5];
    > struct foo extra[NUM_EXTRA_FOOS];
    > } all_foos = {
    > { { 1 }, { 2 }, { 3 }, { 4 }, { 5 } },
    > { { 0 } }
    > };
    >
    > #define foos all_foos.builtin
    >
    > I believe that I can effectively use foos[] as an array with 10 (5 +
    > NUM_EXTRA_FOOS) elements.
    >
    > * Is my belief correct?


    The struct all_foos will be at least large enough for 10
    elements, possibly larger if there's (perverse) padding.

    However, trying to use all_foos.builtin[5] might not work
    (see "struct hack") and even if it works it is not necessarily
    the case that &all_foos.builtin[4]+1 == &all_foos.extra[0]. You
    need to use something like

    #define foos ((struct foo*)&all_foos)

    > * Is there any danger of the compiler inserting unwanted padding between
    > the builtin and extra members of the anonymous struct?


    In principle, yes. Padding can appear after any struct element,
    even if the implementor's reasons for putting it there don't seem
    convincing.

    > * Is there a better way to do this?


    struct foo foos[5 + NUM_EXTRA_FOOS] =
    { {1}, {2}, {3}, {4}, {5} };

    The compiler might warn about the incomplete initializer, but C
    defines the effect: The extras are initialized to zero-value. You
    might be able to suppress the warning with a C99-style initializer:

    struct foo foos[5 + NUM_EXTRA_FOOS] =
    { {1}, {2}, {3}, {4}, {5}, [5+NUM_EXTRA_FOOS-1] = {0} );

    .... or even

    struct foo foos[] =
    { {1}, {2}, {3}, {4}, {5}, [5+NUM_EXTRA_FOOS-1] = {0} );

    --
    Eric Sosman
    d
     
    Eric Sosman, Aug 4, 2012
    #2
    1. Advertising

  3. Ian Pilcher

    Philip Lantz Guest

    Ian Pilcher wrote:
    > I need to create a static array of structures with the following
    > characteristics:
    >
    > * The first few members of the array are pre-initialized
    > * The remaining members of the array are initialized to "zero"
    > * The number of additional members is determined by a #defined constant,
    > independently of the number of pre-initialized members
    >
    > Here's what I've come up with:
    >
    >
    > #define NUM_EXTRA_FOOS 5
    >
    > struct foo {
    > int data;
    > };
    >
    > static struct {
    > struct foo builtin[5];
    > struct foo extra[NUM_EXTRA_FOOS];
    > } all_foos = {
    > { { 1 }, { 2 }, { 3 }, { 4 }, { 5 } },
    > { { 0 } }
    > };
    >
    > #define foos all_foos.builtin
    >
    > I believe that I can effectively use foos[] as an array with 10 (5 +
    > NUM_EXTRA_FOOS) elements.
    >
    > * Is my belief correct?


    It's undefined behavior, but it will work with most, if not all,
    compilers.

    > * Is there any danger of the compiler inserting unwanted padding between
    > the builtin and extra members of the anonymous struct?


    A compiler is allowed to add padding between any two structure members,
    but I doubt that any would add padding here.

    > * Is there a better way to do this?


    Yes, this is much better:

    #define NUM_EXTRA_FOOS 5

    struct foo {
    int data;
    };

    static struct foo foos[5+NUM_EXTRA_FOOS] = {
    { 1 }, { 2 }, { 3 }, { 4 }, { 5 },
    };

    All members beyond those for which there are explicit initializers are
    guaranteed to be initialized to 0.

    When I was first reading the question, I guessed that you would want the
    compiler to count the number of initializers and then add NUM_EXTRA_FOOS
    to that, but your example didn't show it, so I didn't try to answer that
    question. (I'm not sure whether there's an answer; I think there might
    be, but I suspect it would be ugly.)
     
    Philip Lantz, Aug 4, 2012
    #3
  4. Ian Pilcher

    Jens Gustedt Guest

    Am 04.08.2012 04:05, schrieb Ian Pilcher:
    > I need to create a static array of structures with the following
    > characteristics:
    >
    > * The first few members of the array are pre-initialized
    > * The remaining members of the array are initialized to "zero"
    > * The number of additional members is determined by a #defined constant,
    > independently of the number of pre-initialized members
    > #define NUM_EXTRA_FOOS 5



    Yes this can be done even without much preprocessor magic.

    Defining your initializers in a macro

    #define FIRST_ELEMS { 1 }, { 2 }, { 3 }, { 4 }, { 5 }

    and then replace your struct definition by just an array where the size
    expression is constructed from the sizeof of a compount literal.

    struct foo all_foos[NUM_EXTRA_FOOS + sizeof((struct foo[]){
    FIRST_ELEMS})/sizeof(struct foo)] = {
    FIRST_ELEMS,
    };

    Preprocessor magic can also be used to generated some fixed length list
    of initializers, if you prefer that, but this is a bit more involved.

    Jens
     
    Jens Gustedt, Aug 4, 2012
    #4
  5. Ian Pilcher

    Ian Pilcher Guest

    On 08/03/2012 09:43 PM, Eric Sosman wrote:
    > On 8/3/2012 10:05 PM, Ian Pilcher wrote:
    >> * Is there a better way to do this?

    >
    > struct foo foos[5 + NUM_EXTRA_FOOS] =
    > { {1}, {2}, {3}, {4}, {5} };
    >
    > The compiler might warn about the incomplete initializer, but C
    > defines the effect: The extras are initialized to zero-value. You
    > might be able to suppress the warning with a C99-style initializer:
    >
    > struct foo foos[5 + NUM_EXTRA_FOOS] =
    > { {1}, {2}, {3}, {4}, {5}, [5+NUM_EXTRA_FOOS-1] = {0} );
    >
    > ... or even
    >
    > struct foo foos[] =
    > { {1}, {2}, {3}, {4}, {5}, [5+NUM_EXTRA_FOOS-1] = {0} );
    >


    There I go over-thinking again. Thanks!

    --
    ========================================================================
    Ian Pilcher
    "If you're going to shift my paradigm ... at least buy me dinner first."
    ========================================================================
     
    Ian Pilcher, Aug 4, 2012
    #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. Ben
    Replies:
    3
    Views:
    459
  2. SaravanaKumar
    Replies:
    6
    Views:
    9,525
    Tony Morris
    Oct 19, 2004
  3. JFCM
    Replies:
    4
    Views:
    5,788
  4. Oodini
    Replies:
    1
    Views:
    1,846
    Keith Thompson
    Sep 27, 2005
  5. mathieu
    Replies:
    3
    Views:
    653
    Bo Persson
    Sep 4, 2009
Loading...

Share This Page