Initialization of an array and symbolic names for index

P

pozz

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?
 
B

Barry Schwarz

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

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

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
 
P

pozz

Barry Schwarz ha scritto:
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.

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

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.

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 },
....
 
B

Barry Schwarz

Barry Schwarz ha scritto:

snip issues no longer in question
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 },
...
---

If I change the composition of the struct, I should modify the MACRO definition
in source.c and source.h, so I must continue preserving the coeherence of two or
three files.

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
 

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

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top