Initialization of an array and symbolic names for index

Discussion in 'C Programming' started by pozz, Apr 28, 2007.

  1. pozz

    pozz Guest

    Hi all!

    In source.h, I define a struct and the symbolic names of the indexes:
    --- source.h ---
    typedef struct {
    type field1;
    type field2;
    ...
    type fieldm;
    } mystruct;

    extern mystruct mys;

    enum MYSTRUCT_INDEX {
    RECORD1 = 0,
    RECORD2,
    ...
    RECORDn,
    };
    ---

    In source.c, I initialize the struct:
    --- source.c ---
    #include "source.h"

    mystruct mys[] = {
    { <field11>, <field12>, ..., <field1m> },
    { <field21>, <field22>, ..., <field2m> },
    ...
    { <fieldn1>, <fieldn2>, ..., <fieldnm> },
    };
    ---


    In this way, in a third C source file I can include "source.h" and access
    the array by the symbolic names:
    --- third.c ---
    #include "source.h"

    ....
    if( mys[RECORDx].fieldy==... )
    ....
    ---

    This system works well but there is a drawback. When I insert a new record in
    the middle of the array I should remember to change and re-align the enumeration
    in the source.h file. Is there a way, maybe using some preprocessor directives,
    so that I modify/reorder/insert the records only in a point and maintain the
    coherence in the enumeration?
     
    pozz, Apr 28, 2007
    #1
    1. Advertisements

  2. How can this work? Your header file declares mys to be a single
    struct. Your code in third.c accesses mys as an array. You should be
    getting a syntax error.
    After you fix the above problem, the answer is still no.

    Adding a new element to the array is done by updating source.c and
    then compiling it. At this point in time, source.h must exist in
    order to be included. Anything you do at this time, such as
    preprocessing directives in source.c, will affect only the object file
    being generated. Nothing will ever be written back to source.h.
    #include is an input operation, not an update one. When you compile
    third.c, source.h does not "remember" anything that happened while
    compiling source.c.


    Remove del for email
     
    Barry Schwarz, Apr 29, 2007
    #2
    1. Advertisements

  3. pozz

    pozz Guest

    Barry Schwarz ha scritto:
    You are right. In source.h I should declare:
    --- source.h ---
    ....
    extern mystruct mys[];
    ....
    ---

    Ok, I agree with you, but I needn't to have the same structure of files as
    above. I can use a third file (array.def) to list the names and the values and
    include it in source.h and source.c, of course with some preprocessing tricks.

    I was thinking about the following solution.

    --- array.def ---
    MACRO( RECORD1, value1 )
    MACRO( RECORD2, value2 )
    ....
    MACRO( RECORDn, valuen )
    ---

    --- source.h ---
    #undef MACRO
    #define MACRO(sym,val) sym,

    typedef struct {
    int value;
    } mystruct;

    extern mystruct mys[];

    enum MYSTRUCT_INDEX = {
    #include "array.def"
    };
    ---

    --- source.c ---
    #undef MACRO
    #define MACRO(sym,val) { val },

    mystruct mys[] = {
    #include "array.def"
    };
    ---


    The above solution works well, but there is a little difference with the first
    scenario. Here the struct mystruct is composed by only one member. My real
    struct is composed by several fields.
    In this case, I should define MACRO in source.c and source.h in the following way:
    --- source.h ---
    ....
    #undef MACRO
    #define MACRO(sym, f1, f2, ..., fm) sym,
    ....
    ---
    --- source.c ---
    ....
    #undef MACRO
    #define MACRO(sym, f1, f2, ..., fm) { f1, f2, ..., fm },
    ....
     
    pozz, Apr 29, 2007
    #3
  4. snip issues no longer in question
    To consolidate the point of change to a single (header) file which has
    the additional advantage of insuring that all source files that
    include the header will be recompiled when the header changes (if your
    system keeps track), I would try something along the lines of

    #define MACRO1(sym, f1, f2, ..., fm) sym
    #define MACRO2(sym, f1, f2, ..., fm) {f1, f2, ..., fm}
    #define MACRO(macro) \
    macro(sym1, <field11>, <field21>, ..., <fieldm1>), \
    macro(sym2, <field12>, <field22>, ..., <fieldm2>), \
    ...,
    macro(symn, <field1n>, <field2n, ..., <fieldmn>)

    enum MYSTRUCT_INDEX {
    mystruct_dummy = -1, /* probably not necessary since enums
    default to start at 0 but your initial code had initialization */
    MACRO(MACRO1)
    };

    and in source.c
    mystruct mys[] = {MACRO(MACRO2)};

    I'm not sure if the string of macros above requires any kind of
    "circumlocution" along the lines described in faq section 11.17.




    Remove del for email
     
    Barry Schwarz, Apr 29, 2007
    #4
    1. Advertisements

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 (here). After that, you can post your question and our members will help you out.