structures, structures and more structures (questions about nestedstructures)

A

Alfonso Morra

Hi,

I have the ff data types :

typedef enum {
VAL_LONG ,
VAL_DOUBLE ,
VAL_STRING ,
VAL_DATASET
}ValueTypeEnum ;

typedef union {
long lval ;
double fval ;
char* sval ;
void* ptr ;
} Value ;

typedef struct {
int magic ;
int version ;
}Header ;

typedef struct {
char label[20] ;
id int ;
}Key ;

typedef struct {
Header *hdr ;
char *subject ;
int subject_len ;
Key key ;
ValueTypeEnum type ;
Value value ;
int text_len ;
int size ;
}MotherStruct ;


If I have a variable declared as ff:

MotherStruct *pMS = calloc(1,sizeof(MotherStruct*)) ;

1). Do I have to allocate memory seperately for each individual nested
pointer in the structure (i.e. hdr and subject?). I guess the answer is
yes - but I just need to be sure (see question 3 below).

2). How do I calculate the size (in bytes) of the structure MotherStruct
- so that I can use a function like memcpy to copy this memory block to
another memory block ?

3). Finally, (this is related in a way to the first question). If I just
call free on pMS is all the memory that was allocated freed (is the
answer the same if I have to issue seperate calls to allocate memory to
the individual nested pointers - i.e. will a single call to free(pMs)
free any memory allocated to pointers nested within the structure - OR
do I need to free each of the nested pointers before finally freeing the
memory block pointed to by pMS ?

Tkx
 
M

Mike Wahler

Alfonso Morra said:
Hi,

I have the ff data types :

typedef enum {
VAL_LONG ,
VAL_DOUBLE ,
VAL_STRING ,
VAL_DATASET }ValueTypeEnum ;

typedef union {
long lval ;
double fval ;
char* sval ;
void* ptr ;
} Value ;

typedef struct {
int magic ;
int version ;
}Header ;

typedef struct {
char label[20] ;
id int ;
}Key ;

typedef struct {
Header *hdr ;
char *subject ;
int subject_len ;
Key key ;
ValueTypeEnum type ;
Value value ;
int text_len ;
int size ;
}MotherStruct ;


If I have a variable declared as ff:

MotherStruct *pMS = calloc(1,sizeof(MotherStruct*)) ;

1). Do I have to allocate memory seperately for each individual nested
pointer in the structure (i.e. hdr and subject?).

Yes, if you want those pointers to point to objects of
those types.
I guess the answer is yes - but I just need to be sure (see question 3
below).

2). How do I calculate the size (in bytes) of the structure MotherStruct
sizeof(MotherStruct)

- so that I can use a function like memcpy to copy this memory block to
another memory block ?

Also remember you'll need to allocate memory for the pointers
to point to.
3). Finally, (this is related in a way to the first question). If I just
call free on pMS is all the memory that was allocated freed

No. Each call to 'malloc()' must be matched by a call to 'free()'
(is the answer the same if I have to issue seperate calls to allocate
memory to the individual nested pointers - i.e. will a single call to
free(pMs) free any memory allocated to pointers nested within the
structure


No.

- OR
do I need to free each of the nested pointers before finally freeing the
memory block pointed to by pMS ?

Match each 'malloc()' with a 'free()'

And don't forget to test the return value for each call to
'malloc()' (it will return NULL if it fails).

-Mike
 
A

Alfonso Morra

Mike said:
Hi,

I have the ff data types :

typedef enum {
VAL_LONG ,
VAL_DOUBLE ,
VAL_STRING ,
VAL_DATASET }ValueTypeEnum ;

typedef union {
long lval ;
double fval ;
char* sval ;
void* ptr ;
} Value ;

typedef struct {
int magic ;
int version ;
}Header ;

typedef struct {
char label[20] ;
id int ;
}Key ;

typedef struct {
Header *hdr ;
char *subject ;
int subject_len ;
Key key ;
ValueTypeEnum type ;
Value value ;
int text_len ;
int size ;
}MotherStruct ;


If I have a variable declared as ff:

MotherStruct *pMS = calloc(1,sizeof(MotherStruct*)) ;

1). Do I have to allocate memory seperately for each individual nested
pointer in the structure (i.e. hdr and subject?).


Yes, if you want those pointers to point to objects of
those types.

I guess the answer is yes - but I just need to be sure (see question 3
below).

2). How do I calculate the size (in bytes) of the structure MotherStruct


sizeof(MotherStruct)


This is the only answer that suprised me (in fact I don't believe its
the correct answer). I used to think this was the correct answer. But if
you think about it, it can't be (at least, I can't see how it can be).
How can sizeof know how much memory you have allocated for the char*
(for example)?. The number returned by sizeof is independent of the size
of the string that has been allocated for the member subject - so I
think sizeof can be used for a simple structure with basic data types -
whenever you have nested pointers, all bets are off. I think the correct
way of doing this is to navigate the structure and sum up
(sizeof(data_type) x number of data_type) all the way through all the
members of the struct and any nested pointers - that makes sense from a
logical point of view - but it would be great if someone could either
confirm it or point me to a reference that shows me why my thinking is
wrong.

But thanks for the other two answers.
 
M

Mike Wahler

Alfonso Morra said:
Mike said:
Hi,

I have the ff data types :

typedef enum {
VAL_LONG ,
VAL_DOUBLE ,
VAL_STRING ,
VAL_DATASET }ValueTypeEnum ;

typedef union {
long lval ;
double fval ;
char* sval ;
void* ptr ;
} Value ;

typedef struct {
int magic ;
int version ;
}Header ;

typedef struct {
char label[20] ;
id int ;
}Key ;

typedef struct {
Header *hdr ;
char *subject ;
int subject_len ;
Key key ;
ValueTypeEnum type ;
Value value ;
int text_len ;
int size ;
}MotherStruct ;


If I have a variable declared as ff:

MotherStruct *pMS = calloc(1,sizeof(MotherStruct*)) ;

1). Do I have to allocate memory seperately for each individual nested
pointer in the structure (i.e. hdr and subject?).


Yes, if you want those pointers to point to objects of
those types.

I guess the answer is yes - but I just need to be sure (see question 3
below).

2). How do I calculate the size (in bytes) of the structure MotherStruct


sizeof(MotherStruct)


This is the only answer that suprised me (in fact I don't believe its the
correct answer).

Yes, it is correct. It will return the number of bytes used
by a type 'MotherStruct' object. This size includes the size
of all members, including pointers. What those pointers point
to (if anything) is not part of the 'MotherStruct' object.
I used to think this was the correct answer.

It is.
But if you think about it, it can't be (at least, I can't see how it can
be). How can sizeof know how much memory you have allocated for the char*
(for example)?.

It doesn't. That memory is not part of the 'MotherStruct' object,
only the pointer is.
The number returned by sizeof is independent of the size of the string that
has been allocated for the member subject

Yes, because that memory is not part of MotherStruct.
- so I think sizeof can be used for a simple structure with basic data
types -

Yes. Pointers are such types. Again, what they point to is not
part of the structure.
whenever you have nested pointers, all bets are off.
Nope.

I think the correct way of doing this is to navigate the structure and sum
up (sizeof(data_type) x number of data_type) all the way through all the
members of the struct and any nested pointers - that makes sense from a
logical point of view - but it would be great if someone could either
confirm it or point me to a reference that shows me why my thinking is
wrong.

Perhaps you asked the wrong question. :) Yes, if you want to calculate
the size of all memory (including allocated) *associated* with MotherStruct,
that's how to do it.

Your question was:
2). How do I calculate the size (in bytes) of the structure MotherStruct

The correct answer is what I gave:
sizeof(MotherStruct).
But thanks for the other two answers.

You're welcome.

-Mike
 
A

Alfonso Morra

Mike said:
Mike Wahler wrote:

Hi,

I have the ff data types :

typedef enum {
VAL_LONG ,
VAL_DOUBLE ,
VAL_STRING ,
VAL_DATASET }ValueTypeEnum ;

typedef union {
long lval ;
double fval ;
char* sval ;
void* ptr ;
} Value ;

typedef struct {
int magic ;
int version ;
}Header ;

typedef struct {
char label[20] ;
id int ;
}Key ;

typedef struct {
Header *hdr ;
char *subject ;
int subject_len ;
Key key ;
ValueTypeEnum type ;
Value value ;
int text_len ;
int size ;
}MotherStruct ;


If I have a variable declared as ff:

MotherStruct *pMS = calloc(1,sizeof(MotherStruct*)) ;

1). Do I have to allocate memory seperately for each individual nested
pointer in the structure (i.e. hdr and subject?).


Yes, if you want those pointers to point to objects of
those types.



I guess the answer is yes - but I just need to be sure (see question 3
below).

2). How do I calculate the size (in bytes) of the structure MotherStruct


sizeof(MotherStruct)


This is the only answer that suprised me (in fact I don't believe its the
correct answer).


Yes, it is correct. It will return the number of bytes used
by a type 'MotherStruct' object. This size includes the size
of all members, including pointers. What those pointers point
to (if anything) is not part of the 'MotherStruct' object.

I used to think this was the correct answer.


It is.

But if you think about it, it can't be (at least, I can't see how it can
be). How can sizeof know how much memory you have allocated for the char*
(for example)?.


It doesn't. That memory is not part of the 'MotherStruct' object,
only the pointer is.

The number returned by sizeof is independent of the size of the string that
has been allocated for the member subject


Yes, because that memory is not part of MotherStruct.

- so I think sizeof can be used for a simple structure with basic data
types -


Yes. Pointers are such types. Again, what they point to is not
part of the structure.

whenever you have nested pointers, all bets are off.

Nope.


I think the correct way of doing this is to navigate the structure and sum
up (sizeof(data_type) x number of data_type) all the way through all the
members of the struct and any nested pointers - that makes sense from a
logical point of view - but it would be great if someone could either
confirm it or point me to a reference that shows me why my thinking is
wrong.


Perhaps you asked the wrong question. :) Yes, if you want to calculate
the size of all memory (including allocated) *associated* with MotherStruct,
that's how to do it.

Your question was:
2). How do I calculate the size (in bytes) of the structure MotherStruct

The correct answer is what I gave:
sizeof(MotherStruct).

But thanks for the other two answers.


You're welcome.

-Mike
Tkx for the clarification ;-)
 
E

Emmanuel Delahaye

Alfonso Morra wrote on 24/09/05 :
Hi,

I have the ff data types :

typedef enum {
VAL_LONG ,
VAL_DOUBLE ,
VAL_STRING ,
VAL_DATASET
}ValueTypeEnum ;

typedef union {
long lval ;
double fval ;
char* sval ;
void* ptr ;
} Value ;

typedef struct {
int magic ;
int version ;
}Header ;

typedef struct {
char label[20] ;
id int ;
}Key ;

typedef struct {
Header *hdr ;
char *subject ;
int subject_len ;
Key key ;
ValueTypeEnum type ;
Value value ;
int text_len ;
int size ;
}MotherStruct ;

If I have a variable declared as ff:

MotherStruct *pMS = calloc(1,sizeof(MotherStruct*)) ;

Not portable. Filling the memory block with all bits to zero may
produce an unexpected behaviour. For example, a pointer with all bits
to zero is not necessarely a NULL pointer. It's
implementation-dependent. Same problem with floating points. Please
read archives, this subject has been discussed ad-nauseam...
1). Do I have to allocate memory seperately for each individual nested
pointer in the structure (i.e. hdr and subject?). I guess the answer is yes -
but I just need to be sure (see question 3 below).

Yes. There is no magic in C. all mis explicit. If you want magic, build
you own 'constructor' function. A common approach.
2). How do I calculate the size (in bytes) of the structure MotherStruct - so
that I can use a function like memcpy to copy this memory block to another
memory block ?

You don't. The = operator does the job. Of course, the pointed blocks
are not copied. Once again, if you want magic, build your own 'copy'
function. If you insist (not typed pointers in a generic context), the
sizeof operator returns the sizeof of any typed object.

BTW, I feel a sort of design error... do you really need to copy such a
structure ? As far as possible, memory copies are to be avoided...
3). Finally, (this is related in a way to the first question). If I just call
free on pMS is all the memory that was allocated freed (is the answer the
same if I have to issue seperate calls to allocate memory to the individual
nested pointers - i.e. will a single call to free(pMs) free any memory
allocated to pointers nested within the structure - OR do I need to free each
of the nested pointers before finally freeing the memory block pointed to by
pMS ?

All what have been allocated must be explicitely freed. Once again, if
you want magic, build your own 'destructor'.

The RTL (standard C run-time library) uses such a approach with the
FILE object :

- Constructor : fopen()
- Destructor : fclose()

a good source of inspiration...

--
Emmanuel
The C-FAQ: http://www.eskimo.com/~scs/C-faq/faq.html
The C-library: http://www.dinkumware.com/refxc.html

"Clearly your code does not meet the original spec."
"You are sentenced to 30 lashes with a wet noodle."
-- Jerry Coffin in a.l.c.c++
 
E

Emmanuel Delahaye

Alfonso Morra wrote on 24/09/05 :
This is the only answer that suprised me (in fact I don't believe its the
correct answer).

It *is* the correct answer, but your structure being non linear (uses
pointers), it only concerns the structure itself (including the
pointers), **but not the pointed blocks**.

C is just straight and simple. Nothing is hidden or made in your back.
I used to think this was the correct answer. But if you
think about it, it can't be (at least, I can't see how it can be). How can
sizeof know how much memory you have allocated for the char* (for example)?.
The number returned by sizeof is independent of the size of the string that
has been allocated for the member subject - so I think sizeof can be used for
a simple structure with basic data types - whenever you have nested pointers,
all bets are off. I think the correct way of doing this is to navigate the
structure and sum up (sizeof(data_type) x number of data_type) all the way
through all the members of the struct and any nested pointers - that makes
sense from a logical point of view - but it would be great if someone could
either confirm it or point me to a reference that shows me why my thinking is
wrong.

But thanks for the other two answers.

If you have pointed blocks with flexible size, you must keep a track of
the size. A common approach for a flexible string :

struct my_string
{
char *s;
size_t size;
};

a generic approach :

struct my_vector
{
void *p;
size_t size_of_an_element;
size_t number_of_elements;
};


--
Emmanuel
The C-FAQ: http://www.eskimo.com/~scs/C-faq/faq.html
The C-library: http://www.dinkumware.com/refxc.html

I once asked an expert COBOL programmer, how to
declare local variables in COBOL, the reply was:
"what is a local variable?"
 
A

Antonio Contreras

Alfonso said:
Hi,

I have the ff data types :

typedef enum {
VAL_LONG ,
VAL_DOUBLE ,
VAL_STRING ,
VAL_DATASET
}ValueTypeEnum ;

typedef union {
long lval ;
double fval ;
char* sval ;
void* ptr ;
} Value ;

typedef struct {
int magic ;
int version ;
}Header ;

typedef struct {
char label[20] ;
id int ;
}Key ;

typedef struct {
Header *hdr ;
char *subject ;
int subject_len ;
Key key ;
ValueTypeEnum type ;
Value value ;
int text_len ;
int size ;
}MotherStruct ;


If I have a variable declared as ff:

MotherStruct *pMS = calloc(1,sizeof(MotherStruct*)) ;

<snip 3 questionz>

Leaving aside your questions, which have already been adressed by other
people, I think your call to calloc is ill written. Shouldn't it be:

MotherStruct *pMS = calloc(1, sizeof(MotherStruct));

???

You're allocating memory for a pointer to MotherStruct, not for a
MotherStruct. If you dereference pMS you'll invoke undefined behaviour.
Unless there's something I'm missing here.
 
E

Emmanuel Delahaye

Antonio Contreras wrote on 24/09/05 :
Leaving aside your questions, which have already been adressed by other
people, I think your call to calloc is ill written. Shouldn't it be:

MotherStruct *pMS = calloc(1, sizeof(MotherStruct));

You're allocating memory for a pointer to MotherStruct, not for a
MotherStruct. If you dereference pMS you'll invoke undefined behaviour.
Unless there's something I'm missing here.

Good catch.

--
Emmanuel
The C-FAQ: http://www.eskimo.com/~scs/C-faq/faq.html
The C-library: http://www.dinkumware.com/refxc.html

I once asked an expert COBOL programmer, how to
declare local variables in COBOL, the reply was:
"what is a local variable?"
 
A

Alfonso Morra

Emmanuel said:
Alfonso Morra wrote on 24/09/05 :
Hi,

I have the ff data types :

typedef enum {
VAL_LONG ,
VAL_DOUBLE ,
VAL_STRING ,
VAL_DATASET
}ValueTypeEnum ;

typedef union {
long lval ;
double fval ;
char* sval ;
void* ptr ;
} Value ;

typedef struct {
int magic ;
int version ;
}Header ;

typedef struct {
char label[20] ;
id int ;
}Key ;

typedef struct {
Header *hdr ;
char *subject ;
int subject_len ;
Key key ;
ValueTypeEnum type ;
Value value ;
int text_len ;
int size ;
}MotherStruct ;

If I have a variable declared as ff:

MotherStruct *pMS = calloc(1,sizeof(MotherStruct*)) ;


Not portable. Filling the memory block with all bits to zero may produce
an unexpected behaviour. For example, a pointer with all bits to zero is
not necessarely a NULL pointer. It's implementation-dependent. Same
problem with floating points. Please read archives, this subject has
been discussed ad-nauseam...
1). Do I have to allocate memory seperately for each individual nested
pointer in the structure (i.e. hdr and subject?). I guess the answer
is yes - but I just need to be sure (see question 3 below).


Yes. There is no magic in C. all mis explicit. If you want magic, build
you own 'constructor' function. A common approach.
2). How do I calculate the size (in bytes) of the structure
MotherStruct - so that I can use a function like memcpy to copy this
memory block to another memory block ?


You don't. The = operator does the job. Of course, the pointed blocks
are not copied. Once again, if you want magic, build your own 'copy'
function. If you insist (not typed pointers in a generic context), the
sizeof operator returns the sizeof of any typed object.

BTW, I feel a sort of design error... do you really need to copy such a
structure ? As far as possible, memory copies are to be avoided...
3). Finally, (this is related in a way to the first question). If I
just call free on pMS is all the memory that was allocated freed (is
the answer the same if I have to issue seperate calls to allocate
memory to the individual nested pointers - i.e. will a single call to
free(pMs) free any memory allocated to pointers nested within the
structure - OR do I need to free each of the nested pointers before
finally freeing the memory block pointed to by pMS ?


All what have been allocated must be explicitely freed. Once again, if
you want magic, build your own 'destructor'.

The RTL (standard C run-time library) uses such a approach with the FILE
object :

- Constructor : fopen()
- Destructor : fclose()

a good source of inspiration...
Are you talking about ctors and dtors as in C++ ?
 
A

Alfonso Morra

Antonio said:
Alfonso said:
Hi,

I have the ff data types :

typedef enum {
VAL_LONG ,
VAL_DOUBLE ,
VAL_STRING ,
VAL_DATASET
}ValueTypeEnum ;

typedef union {
long lval ;
double fval ;
char* sval ;
void* ptr ;
} Value ;

typedef struct {
int magic ;
int version ;
}Header ;

typedef struct {
char label[20] ;
id int ;
}Key ;

typedef struct {
Header *hdr ;
char *subject ;
int subject_len ;
Key key ;
ValueTypeEnum type ;
Value value ;
int text_len ;
int size ;
}MotherStruct ;


If I have a variable declared as ff:

MotherStruct *pMS = calloc(1,sizeof(MotherStruct*)) ;


<snip 3 questionz>

Leaving aside your questions, which have already been adressed by other
people, I think your call to calloc is ill written. Shouldn't it be:

MotherStruct *pMS = calloc(1, sizeof(MotherStruct));

???

You're allocating memory for a pointer to MotherStruct, not for a
MotherStruct. If you dereference pMS you'll invoke undefined behaviour.
Unless there's something I'm missing here.

Well spotted. That was a typo. I changed the line and posted it before
checking it. My Bad.
 

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,734
Messages
2,569,441
Members
44,832
Latest member
GlennSmall

Latest Threads

Top