Optional elements in a structure declaration? ( URGENT)

Z

zoltan

Hi,
Consider a structure as follows :

struct dummy
{

int a;
int b;
int c;
};

My program has two types of applications - one that uses all 3
elements of the structure ( a,b and c) and the other application which
uses only elements a and b of the same structure.

My question is, is there any way to use the same structure for both
situations such that depending on some flag, I can choose to allocate
memory only for elements a and b ( type 2) or for all 3 elements ( type
1). I do not want to use two different structures for the same.

Thanks,

Mohd. Imaduddin
 
V

Vladimir S. Oka

zoltan said:
Hi,
Consider a structure as follows :

struct dummy
{

int a;
int b;
int c;
};

My program has two types of applications - one that uses all 3
elements of the structure ( a,b and c) and the other application which
uses only elements a and b of the same structure.

My question is, is there any way to use the same structure for both
situations such that depending on some flag, I can choose to allocate
memory only for elements a and b ( type 2) or for all 3 elements ( type
1). I do not want to use two different structures for the same.

Simple answer: use the same structure (as above), and just ignore the
third element.

If this is not good enough for your application, then let us know
exactly why. If your structure consists of more than just `int`s say so
as well. Without details it's more difficult to offer options.

One other option: If your data is more complex than an `int`, why not
make structure members pointers to data, and only allocate memory as
needed. You'd still carry three pointers around in both applications,
but see also:

OTH, if your two applications are independent, why not use something
like:

struct dummy
{

int a;
int b;
#ifdef APP_1
int c;
#endif
};

And #define APP_1 in the first, but not in the second.
 
I

Imad

Thanks very much, but I already considered both approaches.

The thing is I will be using the structure for parsing a compressed
file. If the compressed data is of say TYPE A I shall use only two
elements. If it is of say TYPE B, I will be using all the three. For
reasons of efficiency, I don't want to use the third element. And I
will be using array of the same structure for storing the information.
So using #ifdef is out of question, since I will have to declare the
array in the beginning itself. Also, by using pointers I will still
have a third dummy variable which again is not needed for TYPE A.
 
P

pete

Imad said:
Thanks very much, but I already considered both approaches.

The thing is I will be using the structure for parsing a compressed
file. If the compressed data is of say TYPE A I shall use only two
elements. If it is of say TYPE B,

Why only one type of data structure for two kinds of file data?
 
I

imad

Since it will be easier to manage, also both kinds of data will be
present in the same file, so it will be more convenient to view any
kind of data about the file since everything is present in a single
structure.
 
V

Vladimir S. Oka

Imad said:
Thanks very much, but I already considered both approaches.

The thing is I will be using the structure for parsing a compressed
file. If the compressed data is of say TYPE A I shall use only two
elements. If it is of say TYPE B, I will be using all the three. For
reasons of efficiency, I don't want to use the third element. And I
will be using array of the same structure for storing the information.
So using #ifdef is out of question, since I will have to declare the
array in the beginning itself. Also, by using pointers I will still
have a third dummy variable which again is not needed for TYPE A.

Please quote what and who you're replying to. Otherwise, your posts may
make little to no sense for many people. Please, read
<http://cfaj.freeshell.org/google/> before posting again.

As for your problem, as you describe it, and the constraints, I'm
afraid there's no way to do that in C, AFAIK. Others may know better
though (but may not bother unless you follow posting guidelines above).

As an aside: if you have so much data that carrying and extra pointer
around is out of question, declaring an array to hold it may not be
good practice either. If you don't know how much data you'll get, an
array of static size may prove wastful in memory terms, possibly even
more than an extra pointer per element. If you do know how much data
you'll get, and you know you'll have enough memory for your array, then
you may be able to calculate with certainty whether you can afford an
extra element or not.
 
P

pete

zoltan said:
Hi,
Consider a structure as follows :

struct dummy
{

int a;
int b;
int c;
};

My program has two types of applications - one that uses all 3
elements of the structure ( a,b and c) and the other application which
uses only elements a and b of the same structure.

My question is, is there any way to use the same structure for both
situations such that depending on some flag, I can choose to allocate
memory only for elements a and b ( type 2)
or for all 3 elements ( type
1). I do not want to use two different structures for the same.

A struct with all same type elements
can sometimes be replaced by an array.

int *dummy;

dummy = malloc(flag * sizeof *dummy); /* flag is 2 or 3 */

dummy[0]
dummy[1]
 
C

cayote

zoltan said:
My question is, is there any way to use the same structure for both
situations such that depending on some flag, I can choose to allocate
memory only for elements a and b ( type 2) or for all 3 elements ( type
1). I do not want to use two different structures for the same.

Sorry but my only suggestion is three structures! Rough pseudo-code:

enum struct_type { twoValue, threeValue };

typedef struct {
int a;
int b;
} twoValue_s;

typedef struct {
int a;
int b;
int c;
} threeValue_s;

typedef struct {
enum struct_type struct_e;
void *ptr;
} fileValues;

fileValues myVals[];

then when you know how many values you have, you could do something
like:

myVals[0].struct_e = twoValue;
myVals[0].ptr = malloc( sizeof twoValue_s );

or:

myVals[0].struct_e = threeValue;
myVals[0].ptr = malloc( sizeof threeValue_s );

The struct_e tag tells you how to cast the void *.

switch( myVals[42].struct_e )
{
case twoValue:
func( (twoValue_s*)myVals[42].ptr );
break;
case threeValue:
func( (threeValue_s*)myVals[42].ptr );
break;
}



I know this is terrible, I don't have time to check the code, just
wanted to throw the idea into this discussion. What do people think of
this approach?
 
N

Nick Keighley

zoltan said:
Consider a structure as follows :

struct dummy
{

int a;
int b;
int c;
};

My program has two types of applications - one that uses all 3
elements of the structure ( a,b and c) and the other application which
uses only elements a and b of the same structure.

My question is, is there any way to use the same structure for both
situations such that depending on some flag, I can choose to allocate
memory only for elements a and b ( type 2) or for all 3 elements ( type
1). I do not want to use two different structures for the same.

you could play some nasty tricks with malloc()

[untested code fragment]
typedef struct
{
int type;
int stuff;
int more_stuff;
} File;


typedef struct
{
int type;
int stuff;
} Small_file;


File* create_file()
{
File* f

if ((f = malloc(sizeof File)) == NULL)
abort();

f->type = BIG_FILE;

return f;
}

File* create_small_file()
{
File* f;

if ((f = (File*)malloc(sizeof Small_file)) == NULL)
abort();

f->type = SMALL_FILE;

return f;
}


[end code]

but perhaps I shouldn't encourage this?
 
R

Robin Haigh

Imad said:
Thanks very much, but I already considered both approaches.

The thing is I will be using the structure for parsing a compressed
file. If the compressed data is of say TYPE A I shall use only two
elements. If it is of say TYPE B, I will be using all the three. For
reasons of efficiency, I don't want to use the third element. And I
will be using array of the same structure for storing the information.
So using #ifdef is out of question, since I will have to declare the
array in the beginning itself. Also, by using pointers I will still
have a third dummy variable which again is not needed for TYPE A.


If you've got an array of structs, you have to assume that the size of the
struct is wired into the pointer arithmetic (subscripting) code at compile
time. The only variable-size object you can do pointer arithmetic with is
the new variable-length array in C99. If you can't use those, just malloc a
block of ints and calculate your way around. It needn't be very messy. For
instance

const int a = 0;
const int b = 1;
const int c = 2;
const int d = 3;
int width = c; /* c or d as required */

Then replace
struct dummy *array = malloc (n * sizeof *array)
struct dummy *ps = array
with
int *array = malloc (n * width * sizeof *array)
int *pi = array
and
++ps
with
pi += width
and
ps->a
ps->b
ps->c
with
pi[a]
pi
pi[c]
etc. It only gets messy if you need to replace explicit subscripts, e.g.
ps.a

If you can't afford any wasted struct members, you can't really use structs
at all anyway. They might be padded and come out bigger than you expect.
 
R

Randy Howard

imad wrote
(in article
<[email protected]>):

Note to Google: I hate you.

Back to our regularly scheduled thread... please learn how to
use the google interface to include context.
Since it will be easier to manage, also both kinds of data will be
present in the same file, so it will be more convenient to view any
kind of data about the file since everything is present in a single
structure.

If it actually was easier, then you wouldn't be asking these
questions. "Less code" and "easier" are not the same thing
necessarily.

You said upthread:
The thing is I will be using the structure for parsing a compressed
file. If the compressed data is of say TYPE A I shall use only two
elements. If it is of say TYPE B, I will be using all the three. For
reasons of efficiency, I don't want to use the third element. And I
will be using array of the same structure for storing the information.
So using #ifdef is out of question, since I will have to declare the
array in the beginning itself. Also, by using pointers I will still
have a third dummy variable which again is not needed for TYPE A.

This sounds like some poorly thought out design decisions. If
you have two different types of file data, trying to mash them
into one may not be the best answer. If you really want to
carry both types around in the same containers, then you need a
conditional structure with a flag value to indicate if the "TYPE
B" data is present.

Going back to your original,

#define TYPE_A 0x00
#define TYPE_B 0x01

struct dummy
{
int a;
int b;
int c; /* valid only for TYPE B */
int my_type; /* indicates validity of c entry */
};

When you read in the data, you determine which TYPE it is, set
the appropriate values in the struct, and copy it into your
array. The problem is, every time you use the data, you have to
check/set the my_type entry. That is the cost of smashing two
different TYPES (not C types) into one container. If you reuse
array entries over time, you'll also have to make sure that the
my_type field is updated properly as needed.

On the other hand, if you know for a fact that values for 'c'
have a limited number of possible values, you might be able to
simplify it a bit by using a reserved value (that can not occur
in your data set) for c. This would allow you to set c =
MAGIC_NUMBER in the cases of a TYPE_A data read and eliminate
the extra struct entry, but you still have to manage it
carefully and check the value of c all of the time.
 
K

Keith Thompson

Imad said:
Thanks very much, but I already considered both approaches.

The thing is I will be using the structure for parsing a compressed
file. If the compressed data is of say TYPE A I shall use only two
elements. If it is of say TYPE B, I will be using all the three. For
reasons of efficiency, I don't want to use the third element. And I
will be using array of the same structure for storing the information.
So using #ifdef is out of question, since I will have to declare the
array in the beginning itself. Also, by using pointers I will still
have a third dummy variable which again is not needed for TYPE A.

The original question was posted by "zoltan" <[email protected]>;
this response is from "Imad" <[email protected]>. Are both of you the
same person? Using a consistent identity makes it easier for the rest
of us to follow the discussion.

And of course you need to read <http://cfaj.freeshell.org/google/>.

You still haven't shown us the actual data type that you're trying to
deal with.
 
C

CBFalconer

zoltan said:
.... snip ...

My question is, is there any way to use the same structure for both
situations such that depending on some flag, I can choose to allocate
memory only for elements a and b ( type 2) or for all 3 elements
(type 1). I do not want to use two different structures for the same.

You'll have to use Pascal for that ability.

--
"If you want to post a followup via groups.google.com, don't use
the broken "Reply" link at the bottom of the article. Click on
"show options" at the top of the article, then click on the
"Reply" at the bottom of the article headers." - Keith Thompson
More details at: <http://cfaj.freeshell.org/google/>
Also see <http://www.safalra.com/special/googlegroupsreply/>
 
D

Dave Thompson

You'll have to use Pascal for that ability.

Or Ada. Or use _related_ (OO) types in C++ or Ada -- or Ftn 2005 (!)
-- which aren't strictly 'the same' but can be used as if they were.

Even in C you can just e.g.
malloc (offsetof (struct X, first_excluded_member))
although this is a pain to get correct on first coding and a _royal_
pain to keep correct (consistent) during maintenance. And you can only
do this for dynamic aka 'heap' allocation.

By my reading it is technically UB to do pseudobigptr->smallmember (or
pseudobig.smallmember) if you haven't allocated sufficient space for
all of big, since notionally the abstract machine 'designates' the
entire lvalue and then selects part of it, but I've never seen and
have trouble imagining a non-DS9k implementation where this would
actually fail.

- David.Thompson1 at worldnet.att.net
 
S

S.Tobias

Dave Thompson said:
Or Ada. Or use _related_ (OO) types in C++ or Ada -- or Ftn 2005 (!)
-- which aren't strictly 'the same' but can be used as if they were.

Even in C you can just e.g.
malloc (offsetof (struct X, first_excluded_member))
although this is a pain to get correct on first coding and a _royal_
pain to keep correct (consistent) during maintenance. And you can only
do this for dynamic aka 'heap' allocation.

By my reading it is technically UB to do pseudobigptr->smallmember (or
pseudobig.smallmember) if you haven't allocated sufficient space for
all of big, since notionally the abstract machine 'designates' the
entire lvalue and then selects part of it, but I've never seen and
have trouble imagining a non-DS9k implementation where this would
actually fail.

Such an "actual failure" is described in Eric Sosman's article:
http://groups.google.com/group/comp.lang.c/msg/32c29e5c4e772cf0?hl=en&
From: Eric Sosman <XXX>
Newsgroups: comp.lang.c
Subject: Re: pointer conversion
Date: Tue, 07 Jun 2005 12:19:26 -0400
Message-ID: <[email protected]>

(I disagree only in one point of his analysis: I believe the complier
was deceived by the member access expression - which was disambiguated
through the pointer type - not by the pointer type itself. In any case,
the compiler got its revenge...)
 

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

No members online now.

Forum statistics

Threads
473,754
Messages
2,569,521
Members
44,995
Latest member
PinupduzSap

Latest Threads

Top