Connecting Tech Pros Worldwide Forums | Help | Site Map

Need a GURU! I'm stuck....

Chris LaVelle
Guest
 
Posts: n/a
#1: Jan 17 '08

I don't know the easiest way to explain this so, I'm going to give an
example of how it is today....and what I'm trying to accomplish.

in the header...
typedef struct XXX_ELEMENT_tag
{
UINT8 num;
UINT8 param;
UINT16 fre1;
INT16 a1;
} ;
typedef struct XXX_ELEMENT_tag ELEMENT_T;

#define MAX_ELEMENTS 8
typedef struct XYZ_S_tag {
UINT8 num_elements;
UINT8 flag;
ELEMENT_T element[MAX_E]; /*** This is the spot ***/
} XYZ_S_tag;

And of course the S_tag structure is buried one more structure down. Say
something like:

typedef struct T_TABLE_tag
{
XYZ_S_tag run;
XYZ_S_tag walk;
.... /* alot of these */
XYZ_S_tag crawl;
} TABLE_T;
typedef struct T_TABLE_tag T_table;

And in a C file a global is initialized like this...
T_table t_table =
{
{ /* run */
2, /* Num Elements */
APPLY_WINDOW, /* Flag */
{
/* N p f a */
/* 0 */ { 2, 0, 480, -240 },
/* 1 */ { 0, 0, 0, 500 },
/* 2 */ { 0, 0, 0, 0 },
/* 3 */ { 0, 0, 0, 0 },
/* 4 */ { 0, 0, 0, 0 },
/* 5 */ { 0, 0, 0, 0 },
/* 6 */ { 0, 0, 0, 0 },
/* 7 */ { 0, 0, 0, 0 },
/* 8 */ { 0, 0, 0, 0 },
}
},
{ /* walk */
/* repeat many many times */

}
}

Ok, let's just say element is bigger than my example above and there are
about a 1000 of these, only half of which have data. I've inherited
this code and this table is occupying 300k of memory and memory's tight.
I want to delete all the filler rows and declare element in a way that
the compiler will auto size what it needs for each instance. I have the
number of elements. I would have thought something along the lines of
*element instead of element[MAX_E]. But I get warnings about the
unexpected brace for element. Is there a way to make the compiler(gcc)
auto size the space for me? In the above example I would be deleting
rows 2-8.

Any and all help is appreciated?

Thanks
cj

CJ LaVelle
Guest
 
Posts: n/a
#2: Jan 17 '08

re: Need a GURU! I'm stuck....



when I did the *element, tons of warnings and then errors out saying to
many items for element. I also tried element[] and it didn't like that
at all. The header file errors during compile with incomplete
declaration error. Sorry I don't have it in front of me...

Again, any thoughts or ideas would be appreciated.

Chris LaVelle wrote:
Quote:
>
I don't know the easiest way to explain this so, I'm going to give an
example of how it is today....and what I'm trying to accomplish.
>
in the header...
typedef struct XXX_ELEMENT_tag
{
UINT8 num;
UINT8 param;
UINT16 fre1;
INT16 a1;
} ;
typedef struct XXX_ELEMENT_tag ELEMENT_T;
>
#define MAX_ELEMENTS 8
typedef struct XYZ_S_tag {
UINT8 num_elements;
UINT8 flag;
ELEMENT_T element[MAX_E]; /*** This is the spot ***/
} XYZ_S_tag;
>
And of course the S_tag structure is buried one more structure down. Say
something like:
>
typedef struct T_TABLE_tag
{
XYZ_S_tag run;
XYZ_S_tag walk;
.... /* alot of these */
XYZ_S_tag crawl;
} TABLE_T;
typedef struct T_TABLE_tag T_table;
>
And in a C file a global is initialized like this...
T_table t_table =
{
{ /* run */
2, /* Num Elements */
APPLY_WINDOW, /* Flag */
{
/* N p f a */
/* 0 */ { 2, 0, 480, -240 },
/* 1 */ { 0, 0, 0, 500 },
/* 2 */ { 0, 0, 0, 0 },
/* 3 */ { 0, 0, 0, 0 },
/* 4 */ { 0, 0, 0, 0 },
/* 5 */ { 0, 0, 0, 0 },
/* 6 */ { 0, 0, 0, 0 },
/* 7 */ { 0, 0, 0, 0 },
/* 8 */ { 0, 0, 0, 0 },
}
},
{ /* walk */
/* repeat many many times */
>
}
}
>
Ok, let's just say element is bigger than my example above and there are
about a 1000 of these, only half of which have data. I've inherited
this code and this table is occupying 300k of memory and memory's tight.
I want to delete all the filler rows and declare element in a way that
the compiler will auto size what it needs for each instance. I have the
number of elements. I would have thought something along the lines of
*element instead of element[MAX_E]. But I get warnings about the
unexpected brace for element. Is there a way to make the compiler(gcc)
auto size the space for me? In the above example I would be deleting
rows 2-8.
>
Any and all help is appreciated?
>
Thanks
cj
Richard Heathfield
Guest
 
Posts: n/a
#3: Jan 17 '08

re: Need a GURU! I'm stuck....


Chris LaVelle said:
Quote:
>
I don't know the easiest way to explain this so, I'm going to give an
example of how it is today....and what I'm trying to accomplish.
[Chris LV is trying to get himself a ragged array, but he wants to
initialise it using ordinary array initialisation syntax.]

Alas, no, you can't do this in the way you would like to do it.

You *can*, however, get the behaviour you desire. The easiest way to do it
is probably via a runtime file containing the data, one item per line. If
this can contain an item count at the start of each line, so much the
better. If it can contain a line count at the very start of the file,
that's better still. (But if either or both of those hints-to-the-program
aren't possible, there's a workaround called realloc.)

Define your variable-length data as... well, I was about to suggest that
you use ELEMENT_T *element, but I can't do that with a clear conscience
because the ELEMENT_T identifier is reserved for the implementation! But
whatever type name you end up using, element needs to be a pointer to that
type.

Having decided how many items you want, you do this in your read-loop:

/* we need n items on this line */
t_table.run[i].element = malloc(n * sizeof *t_table.run[i].element);
if(t_table.run[i].element != NULL)
{
read n lots of num, param, fre1, and a1 from the file and store
them in t_table.run[i].element[0] through t_table.run[i].element[n-1]
}


Disadvantage of this technique: the successful running of your program now
requires the existence of this external file.

Advantages: it gives you the memory saving you require; and it allows you
to change the initialisation values without recompiling the code (okay,
whether this is an advantage is a matter of opinion).

--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
Peter Nilsson
Guest
 
Posts: n/a
#4: Jan 17 '08

re: Need a GURU! I'm stuck....


Chris LaVelle <cjlave...@yahoo.comwrote:
Quote:
...
typedef struct XXX_ELEMENT_tag
{
* *UINT8 * num;
* *UINT8 * param;
* *UINT16 *fre1;
* *INT16 * a1;} ;
>
typedef struct XXX_ELEMENT_tag ELEMENT_T;
>
#define MAX_ELEMENTS 8
typedef struct XYZ_S_tag {
* * UINT8 * * num_elements;
* * UINT8 * * flag;
* * ELEMENT_T element[MAX_E]; * */*** This is the spot ***/
>
} XYZ_S_tag;
>
And of course the S_tag structure is buried one more
structure down. Say something like:
>
typedef struct T_TABLE_tag
{
* *XYZ_S_tag run;
* *XYZ_S_tag walk;
* *.... */* alot of these */
* *XYZ_S_tag crawl;} TABLE_T;
>
typedef struct T_TABLE_tag T_table;
>
And in a C file a global is initialized like this...
<snip>
Quote:
>
Ok, let's just say element is bigger than my example
above and there are about a 1000 of these, only half
of which have data. *I've inherited this code and this
table is occupying 300k of memory and memory's tight.
I want to delete all the filler rows and declare
element in a way that the compiler will auto size what
it needs for each instance.*I have the number of
elements. *I would have thought something along the
lines of *element instead of element[MAX_E].
Yes, but that does come at a compromise in that the
pointer takes up space in addition to the array it
points to.
Quote:
>*But I get warnings about the unexpected brace for
element.
Sounds like a syntactical thing. Take a look at...

#include <stdio.h>

#define countof(x) ( (size_t) (sizeof(x)/sizeof*(x)) )

struct thang
{
const char *name;
size_t count;
const char **element;
};

const char *dwarfs[] =
{
"Bashful",
"Doc",
"Dopey",
"Grumpy",
"Happy",
"Sleepy",
"Sneezy"
};

const char *solids[] =
{
"Tetrahedron",
"Octahedron",
"Cube",
"Icosahedron",
"Dodecahedron"
};

struct thang thangs[] =
{
{ "Seven Dwarfs", countof(dwarfs), dwarfs },
{ "Perfect Solids", countof(solids), solids }
};

int main(void)
{
size_t i, j;

for (i = 0; i < countof(thangs); i++)
{
if (i) puts("");
printf("%s:\n", thangs[i].name);
for (j = 0; j < thangs[i].count; j++)
printf(" %s\n", thangs[i].element[j]);
}

return 0;
}

--
Peter
CJ LaVelle
Guest
 
Posts: n/a
#5: Jan 17 '08

re: Need a GURU! I'm stuck....



Firmware, so really no place to stick a file. It has to stay in the
image for now and continue to be a global for madness reasons.

CJ
Richard Heathfield wrote:
Quote:
Chris LaVelle said:
>
>
Quote:
>>I don't know the easiest way to explain this so, I'm going to give an
>>example of how it is today....and what I'm trying to accomplish.
>
>
[Chris LV is trying to get himself a ragged array, but he wants to
initialise it using ordinary array initialisation syntax.]
>
Alas, no, you can't do this in the way you would like to do it.
>
You *can*, however, get the behaviour you desire. The easiest way to do it
is probably via a runtime file containing the data, one item per line. If
this can contain an item count at the start of each line, so much the
better. If it can contain a line count at the very start of the file,
that's better still. (But if either or both of those hints-to-the-program
aren't possible, there's a workaround called realloc.)
>
Define your variable-length data as... well, I was about to suggest that
you use ELEMENT_T *element, but I can't do that with a clear conscience
because the ELEMENT_T identifier is reserved for the implementation! But
whatever type name you end up using, element needs to be a pointer to that
type.
>
Having decided how many items you want, you do this in your read-loop:
>
/* we need n items on this line */
t_table.run[i].element = malloc(n * sizeof *t_table.run[i].element);
if(t_table.run[i].element != NULL)
{
read n lots of num, param, fre1, and a1 from the file and store
them in t_table.run[i].element[0] through t_table.run[i].element[n-1]
}
>
>
Disadvantage of this technique: the successful running of your program now
requires the existence of this external file.
>
Advantages: it gives you the memory saving you require; and it allows you
to change the initialisation values without recompiling the code (okay,
whether this is an advantage is a matter of opinion).
>
CJ LaVelle
Guest
 
Posts: n/a
#6: Jan 17 '08

re: Need a GURU! I'm stuck....



Firmware, so really no place to stick a file. It has to stay in the
image for now and continue to be a global for madness reasons.

But thanks..

CJ
Richard Heathfield wrote:
Quote:
Chris LaVelle said:
>
>
Quote:
>>I don't know the easiest way to explain this so, I'm going to give an
>>example of how it is today....and what I'm trying to accomplish.
>
>
[Chris LV is trying to get himself a ragged array, but he wants to
initialise it using ordinary array initialisation syntax.]
>
Alas, no, you can't do this in the way you would like to do it.
>
You *can*, however, get the behaviour you desire. The easiest way to do it
is probably via a runtime file containing the data, one item per line. If
this can contain an item count at the start of each line, so much the
better. If it can contain a line count at the very start of the file,
that's better still. (But if either or both of those hints-to-the-program
aren't possible, there's a workaround called realloc.)
>
Define your variable-length data as... well, I was about to suggest that
you use ELEMENT_T *element, but I can't do that with a clear conscience
because the ELEMENT_T identifier is reserved for the implementation! But
whatever type name you end up using, element needs to be a pointer to that
type.
>
Having decided how many items you want, you do this in your read-loop:
>
/* we need n items on this line */
t_table.run[i].element = malloc(n * sizeof *t_table.run[i].element);
if(t_table.run[i].element != NULL)
{
read n lots of num, param, fre1, and a1 from the file and store
them in t_table.run[i].element[0] through t_table.run[i].element[n-1]
}
>
>
Disadvantage of this technique: the successful running of your program now
requires the existence of this external file.
>
Advantages: it gives you the memory saving you require; and it allows you
to change the initialisation values without recompiling the code (okay,
whether this is an advantage is a matter of opinion).
>
Gene
Guest
 
Posts: n/a
#7: Jan 17 '08

re: Need a GURU! I'm stuck....


On Jan 16, 9:00*pm, Chris LaVelle <cjlave...@yahoo.comwrote:
Quote:
I don't know the easiest way to explain this so, I'm going to give an
example of how it is today....and what I'm trying to accomplish.
>
in the header...
typedef struct XXX_ELEMENT_tag
{
* *UINT8 * num;
* *UINT8 * param;
* *UINT16 *fre1;
* *INT16 * a1;} ;
>
typedef struct XXX_ELEMENT_tag ELEMENT_T;
>
#define MAX_ELEMENTS 8
typedef struct XYZ_S_tag {
* * UINT8 * * num_elements;
* * UINT8 * * flag;
* * ELEMENT_T element[MAX_E]; * */*** This is the spot ***/
>
} XYZ_S_tag;
>
And of course the S_tag structure is buried one more structure down. Say
something like:
>
typedef struct T_TABLE_tag
{
* *XYZ_S_tag run;
* *XYZ_S_tag walk;
* *.... */* alot of these */
* *XYZ_S_tag crawl;} TABLE_T;
>
typedef struct T_TABLE_tag T_table;
>
And in a C file a global is initialized like this...
T_table t_table =
{
* * * * { /* run * * **/
* * * * * * * * 2, /* Num Elements */
* * * * * * * * APPLY_WINDOW, /* Flag */
* * * * * * * * {
* * * * * * * * * * * * /* * * * *N *p * f * * a */
* * * * * * * * * * * * /* 0 */ { 2, 0, 480, -240 },
* * * * * * * * * * * * /* 1 */ { 0, 0, * 0, 500},
* * * * * * * * * * * * /* 2 */ { 0, 0, * 0, 0 },
* * * * * * * * * * * * /* 3 */ { 0, 0, * 0, 0 },
* * * * * * * * * * * * /* 4 */ { 0, 0, * 0, 0 },
* * * * * * * * * * * * /* 5 */ { 0, 0, * 0, 0 },
* * * * * * * * * * * * /* 6 */ { 0, 0, * 0, 0 },
* * * * * * * * * * * * /* 7 */ { 0, 0, * 0, 0 },
* * * * * * * * * * * * /* 8 */ { 0, 0, * 0, 0 },
* * * * * * * * }
* * * * },
* * * * { /* walk **/
* * * * * * * /* repeat many many times */
>
* * * * }
>
}
>
Ok, let's just say element is bigger than my example above and there are
about a 1000 of these, only half of which have data. *I've inherited
this code and this table is occupying 300k of memory and memory's tight.
I want to delete all the filler rows and declare element in a way that
the compiler will auto size what it needs for each instance. *I have the
number of elements. *I would have thought something along the lines of
*element instead of element[MAX_E]. *But I get warnings about the
unexpected brace for element. *Is there a way to make the compiler(gcc)
auto size the space for me? *In the above example I would be deleting
rows 2-8.
>
Any and all help is appreciated?
>
Thanks
cj
You have the right idea (one anyway). Replace the mostly ignored
array with a pointer to a correctly sized array.

It sounds like you were trying to intialize a pointer with an
aggregate. Won't work in C. You have to name the array independently
for this to work. You can easily write a perl script to do this
translation. No other code will need changing.

typedef struct XYZ_S_tag {
UINT8 num_elements;
UINT8 flag;
ELEMENT_T *element; /*** Changed to pointer ***/
} XYZ_S_tag;

typedef struct T_TABLE_tag
{
XYZ_S_tag run;
XYZ_S_tag walk;
.... /* alot of these */
XYZ_S_tag crawl;
} TABLE_T;

typedef struct T_TABLE_tag T_table;

ELEMENT_T run_elements[] = {
/* 0 */ { 2, 0, 480, -240 },
/* 1 */ { 0, 0, 0, 500 } };

T_table t_table =
{
{ /* run */
2, /* Num Elements */
APPLY_WINDOW, /* Flag */
run_elements
},
{ /* walk */
/* repeat many many times */

}
}

Another approach is to declare a different record type for each
possible number of elements. If your max is really only 8, this is
reasonable. Preprocessor abuse will help:

#define DECLARE_XYZ(Size) \
typedef struct XYZ_S_ ## Size ## _tag { \
UINT8 num_elements; \
UINT8 flag; \
ELEMENT_T element[Size]; \
} XYZ_S_ ## Size ## _tag

DECLARE_XYZ(1); DECLARE_XYZ(2); DECLARE_XYZ(3);DECLARE_XYZ(4);
DECLARE_XYZ(5); DECLARE_XYZ(6); DECLARE_XYZ(7);DECLARE_XYZ(8);

Now,

typedef struct T_TABLE_tag
{
XYZ_S_2_tag run;
XYZ_S_4_tag walk;
.... /* alot of these */
XYZ_S_1_tag crawl;
} TABLE_T;

T_table t_table =
{
{ /* run */
2, /* Num Elements */
APPLY_WINDOW, /* Flag */
{
/* N p f a */
/* 0 */ { 2, 0, 480, -240 },
/* 1 */ { 0, 0, 0, 500 },
}
},
{ /* walk */
4,
FLAG,
{
/* N p f a */
/* 0 */ { 2, 0, 480, -240 },
/* 1 */ { 0, 0, 0, 500 },
/* 2 */ { 2, 0, 480, -240 },
/* 3 */ { 0, 0, 0, 500 },
}
/* repeat many many times */
}
}

Again a little script will fix you right up...
Peter Nilsson
Guest
 
Posts: n/a
#8: Jan 17 '08

re: Need a GURU! I'm stuck....


Richard Heathfield <r...@see.sig.invalidwrote:
Quote:
...I was about to suggest that you use ELEMENT_T *element,
but I can't do that with a clear conscience because the
ELEMENT_T identifier is reserved for the implementation!
Strictly speaking, it's reserved for use as a macro if
<errno.his included. But since someone might one day
want to include that header, that's normally enough
reason to steer clear of EXXXX identifiers.

--
Peter
dj3vande@csclub.uwaterloo.ca.invalid
Guest
 
Posts: n/a
#9: Jan 17 '08

re: Need a GURU! I'm stuck....


[Please don't top post; responses should go under the relevant quoted
text, and non-relevant quoted text should be removed.]
Quote:
>Richard Heathfield wrote:
Quote:
Quote:
>[Chris LV is trying to get himself a ragged array, but he wants to
>initialise it using ordinary array initialisation syntax.]
>>
>Alas, no, you can't do this in the way you would like to do it.
>>
>You *can*, however, get the behaviour you desire. The easiest way to do it
>is probably via a runtime file containing the data, one item per line. If
>this can contain an item count at the start of each line, so much the
>better. If it can contain a line count at the very start of the file,
>that's better still. (But if either or both of those hints-to-the-program
>aren't possible, there's a workaround called realloc.)
[And mallocate memory and read the data from a file at run time,
allocating only the amount of memory that's actually needed]


In article <_dednYDm5PZTXhPanZ2dnUVZ_qfinZ2d@comcast.com>,
CJ LaVelle <cjlavelle@yahoo.comwrote:
Quote:
>
>Firmware, so really no place to stick a file. It has to stay in the
>image for now and continue to be a global for madness reasons.
You can write code that is set up as a ragged array that's entirely in
the image, and end up with something not entirely unlike this:
(We've lost your original data structure definitions, so I'll use
minimal ones for the purposes of illustration)
--------
struct element
{
/*Stuff that goes in each element*/
};

struct row
{
/*Number of elements in this row*/
int nelems;
struct element *elems;
};

/*The actual data, compacted into a single one-dimensional array*/
struct element *all_elems[]=
{
/*The next seventeen elements are for row 0*/
{ /*initializer for first element in row 0*/ },
/*...sixteen more initializers for row 0...*/

/*The next three elements are for row 1*/
{ /*initializer for first element in row 1*/ },
{ /*initializer for second element in row 1*/ },
{ /*initializer for third element in row 1*/ },

/*The next 42 elements are for row 2*/
{ /*initializer for first element in row 2*/ },
/*...41 more initializers for row 2...*/

/*Initializers for the rest of the rows*/
};

/*We access the data through this array of struct row*/
struct row *rows[]=
{
/*Row 0: 17 elements*/
{17, &all_elems[0]},
/*Row 1: 3 elements*/
{3, &all_elems[17]},
/*Row 2: 42 elements*/
{42, &all_elems[20]},

/*...and for the rest of the rows...*/
};
--------
This will obviously be incredibly tedious and fragile to maintain by
hand; every time something gets added in the middle, every row after
that has to have its initializers updated, and forgetting something or
getting an addition wrong will give you a bug that's likely to be hard
to trace.

It should, however, not be too hard to write a program that reads a
file in the format that Richard H described and writes this code for
you - computers are, after all, extremely good at things that are
tedious and purely mechanical to do by hand. Then all you have to do
is run the code generator as part of your build process, and you get a
nice compact (and statically initialized, which may be important for a
firmware application) internal representation in your image AND an
easy-to-edit input format for your development.


dave

--
Dave Vandervies dj3vande at eskimo dot com
It might actually be true for these groups that "C is a dead language".
At least at the levels they work at, generating AJAX to provide many new
security vulnerabilities. --Jack Klein in comp.lang.c
Closed Thread