how to allocate memory to a member dynamically

R

raghu

Hello ,

This is Raghu. I have a problem in declaring a structure.
Consider
struct hai{
int id;
char sex;
int age;
};
here when a variable is instianted for this structure then immediately
for all members memory is allocated. But I need to allocate memory for
age only if sex is M else the memory should not allocate.
Think you understand the query.
and awaiting for your reply
bye take care
with smile
Raghu
 
J

Jens Thoms Toerring

raghu said:
This is Raghu. I have a problem in declaring a structure.
Consider
struct hai{
int id;
char sex;
int age;
};
here when a variable is instianted for this structure then immediately
for all members memory is allocated. But I need to allocate memory for
age only if sex is M else the memory should not allocate.

Then you can't use the structure like this - a structure _is_ the
set of its components and when you have the compiler create a new
instance of the structure it will give you memory for all its
members. The only way out is to have a pointer in the structure
that you assign memory to manually under certain conditions only,
like in (required error checking left out):

struct hai2 {
int id;
char sex;
int *age;
} person;

/* Assign some value to person.sex here */

if ( person.sex == 'M' ) {
person.age = malloc( sizeof *person.age );
*person.age = 17;
}

Of course, you also have to take care of deallocating the memory before
the structure goes out of scope.

Obvioulsy, this looks stupid in this example (the int pointer probably
requires at least as much memory as an integer), but there are several
situations where such an approach makes a lot of sense.

Regards, Jens
 
M

mark_bluemel

raghu said:
Consider
struct hai{
int id;
char sex;
int age;
};
here when a variable is instianted for this structure then immediately
for all members memory is allocated. But I need to allocate memory for
age only if sex is M else the memory should not allocate.
Think you understand the query.
and awaiting for your reply

I suppose you could do something like this (error handling omitted for
brevity) :-

char sex;
int age;
struct hai *hp;
....
<processing to get the data to work with>
....
if (sex == 'M') {
hp = malloc(sizeof(struct hai));
hp->id = <whatever>;
hp->sex = sex;
hp->age = age;
} else { /* I assume you've validate that sex is 'M' or 'F' */
hp = malloc(sizeof(struct hai) - sizeof(int));
hp->id = <whatever>;
hp->sex = sex;
}

It's ugly and almost guaranteed to cause you grief in later times, but
it does (in some sense) meet your requirement.

However, your requirement is nonsense. Saving 1 machine word per
"struct hai" is not worth bothering with unless you are hugely
memory-constrained, IMNSHO...
 
M

mark_bluemel

..., your requirement is nonsense. Saving 1 machine word per
"struct hai" is not worth bothering with unless you are hugely
memory-constrained, IMNSHO...

As Jens points out, if there is more than just a single word, such as a
nested structure, the presence or absence of which is dependant on
other data in the structure, then a pointer-based solution may be
appropriate...
 
R

raghu

Okay but the problem is i have number of such type of members in a
structure. And instead of a byte I want to check the bit positions. If
i followed ur approach then i have to waste the memory of 4 bytes for
each member. But i don't want to happen like that.
-Raghu
 
C

Christopher Benson-Manica

raghu said:
Okay but the problem is i have number of such type of members in a
structure. And instead of a byte I want to check the bit positions. If
i followed ur approach then i have to waste the memory of 4 bytes for
each member. But i don't want to happen like that.

One idea that buys you infinite flexibility at the cost of one void *,
one int, and 2^n-1 structure definitions (where n is the number of these
members that you don't want to automatically allocate memory for) -
making it a terribly silly idea, really - follows:

enum struct_types { FOO, BAR, FOO_AND_BAR };

struct my_struct {
int baz;
/* other fields */
int struct_type;
void *variable_struct;
};

struct foo {
int foo;
};

struct bar {
int bar;
};

struct foo_and_bar {
int foo;
int bar;
};

struct my_struct *allocate_my_struct( int type ) {
/* Error checking of malloc() calls omitted */
struct my_struct *ret=malloc( sizeof *ret );
switch(type) {
case FOO:
ret->variable_struct=malloc( sizeof(struct foo) );
break;
case BAR:
ret->variable_struct=malloc( sizeof(struct bar) );
break;
case FOO_AND_BAR:
ret->variable_struct=malloc( sizeof(struct foo_and_bar) );
break;
default:
ret->variable_struct=NULL;
}
ret->struct_type=type;
return ret;
}
 
M

mark_bluemel

raghu said:
... the problem is i have number of such type of members in a
structure. And instead of a byte I want to check the bit positions. If
i followed ur approach then i have to waste the memory of 4 bytes for
each member. But i don't want to happen like that.

First point - don't top-post. It's greatly disliked in this group and
you'll lose such friends as you have.

Second point - if that is your problem, then you should have told us
about it first, rather than the trivial reduction of it. I think we
still need a clearer idea of what you are really trying to do before we
can give more than the most general guidance. Christopher's suggestion
seems fairly close though I'd also consider what could be achieved with
(for example) the use of unions...
 
A

Ancient_Hacker

Well, it's hardly worth the effort. If you're allocating with
malloc() there's typically a minium allocation of 8 to 16 bytes, so
saving the "age" field isn much of a savings. In fact often no savings
at all, if malloc does 16-byte alignment for speed.

Also, most people don't live more than 127 years, so you could store
the gender and age in one byte. Either with a union, or by some
convention, such as a signed char where -1 implies female, positive
implies male and gives their age.
 
A

Ancient_Hacker

What you're trying to do can be expressed in better-thought-out
languages such as Pascal, which have the concept of a "variant record",
your structure would look like:

hai = record
id: integer;
case
sex: boolean of
true: ( age: integer );
false: ( );
end;

But in C you don't have that option. You can fake it somewhat by
defining TWO structs, one with and the other without the age field,and
malloc the right one each time.
 
C

CBFalconer

raghu said:
Okay but the problem is i have number of such type of members in a
structure. And instead of a byte I want to check the bit positions.
If i followed ur approach then i have to waste the memory of 4
bytes for each member. But i don't want to happen like that.

Don't top-post, or you will likely be ignored in this group. Your
answer belongs after, or possibly intermixed with, the _snipped_
material you quote. Also you should improve your spelling. The
first person pronoun is I, capitalized. 'your' is spelt as shown.
Using such abortions as i and ur only makes your post hard to read
and is offensive.
 
A

Andrew Poelstra

On Tue, 2006-10-24 at 04:21 -0700, raghu wrote:
Consider
struct hai{
int id;
char sex;
int age;
};
here when a variable is instianted for this structure then immediately
for all members memory is allocated. But I need to allocate memory for
age only if sex is M else the memory should not allocate.
<formalities snipped>

There's no way to do this. You could pull it off using pointers, but
then you'd still have to allocate memory for the pointers itself
(which, chances are, is just as large as an int would be).

If you really need to do this, you should create separate structs
for men and women. In an OO language, you could do this a little
more elegantly than in C.
 
A

Andrew Poelstra

Well, it's hardly worth the effort. If you're allocating with
malloc() there's typically a minium allocation of 8 to 16 bytes, so
saving the "age" field isn much of a savings. In fact often no savings
at all, if malloc does 16-byte alignment for speed.

Also, most people don't live more than 127 years, so you could store
the gender and age in one byte. Either with a union, or by some
convention, such as a signed char where -1 implies female, positive
implies male and gives their age.

Remember to quote context. Yours seems to be the cleverest solution to
the OP's problem, but few can remember what that problem was!

(It was, essentially, "can I only allocate the .age member of a struct
if the .sex member is 'M'"?)
 
M

Michal Nazarewicz

Ancient_Hacker said:
What you're trying to do can be expressed in better-thought-out
languages such as Pascal, which have the concept of a "variant record",
your structure would look like:

hai = record
id: integer;
case
sex: boolean of
true: ( age: integer );
false: ( );
end;

But in C you don't have that option.

The "case" doesn't do anything in your example. It's "the same"
structure as in C99 would be:

#v+
struct hai {
int id;
char sex;
union {
int age;
};
};
#v-

"case" insinde of a "record" in Pascal is very similar to "union" and
still your record hai will consume at least sizeof(integer) +
sizeof(boolean) + sizeof(integer) bytes no mether the value of sex.
 
R

Richard Bos

Andrew Poelstra said:
Remember to quote context. Yours seems to be the cleverest solution to
the OP's problem, but few can remember what that problem was!

Clever, but also wrong. The signed char option works, but is rather
brittle and hard to maintain. The union option simply does not work. You
can't store two things in a byte with a union. You can store _either_
one _or_ the other, and writing to either destroys the other.

What might work, or might not, but is at least correct C, is to use
bitfields. 1 bit for the sex, 7 bits for the age. Both unsigned, of
course. Unfortunately there's no guarantee that you can use unsigned
chars for bitfields (only signed and unsigned int, and in C99 _Bool -
and implementation-defined types, so you _may_ be able to use unsigned
char, but it's not portable), so there's no guarantee that you save any
memory this way, over a simple non-bitfield unsigned char for both.

Richard
 
A

Ancient_Hacker

Michal said:
"case" insinde of a "record" in Pascal is very similar to "union" and
still your record hai will consume at least sizeof(integer) +
sizeof(boolean) + sizeof(integer) bytes no mether the value of sex.


Ah, not exactly. If the record has a "discriminated" variant part,
meaning there's a variable in the record that indicates which variant
this is, as in this example, then when you make a new instance of the
record with new(), you can specify which variant record size you want,
for instance in the above example: new( Rec, true ) would allocate
only enough space for a record with the sex=true option.
 

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
474,434
Messages
2,571,685
Members
48,796
Latest member
Greg L.

Latest Threads

Top