Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C Programming > C beginner: struct inside another struct...

Reply
Thread Tools

C beginner: struct inside another struct...

 
 
Mark McIntyre
Guest
Posts: n/a
 
      04-21-2006
On Sat, 22 Apr 2006 00:37:27 +0000, in comp.lang.c , Yourko
<(E-Mail Removed)> wrote:

>struct _client{
> int fd; // file descriptor
> struct sockaddr_in sock_name;
>} * client;
>
>Later in that program i do:
>client = (struct _client *) malloc(sizeof(struct _client));


The cast is not necessary in C, and can conceal an error. Don't put it
in.

>and later:
>realloc(client, sizeof(struct _client);
>
>Here is my question: is my client pointer an array now?


No, you've just pointed "client" at some different block of memory. If
you want an array, declare one.

struct client ** pclient;

pclient = malloc( 3* sizeof *pclient); // alloc pointers
pclient[0] = malloc(sizeof *pclient[0]); // alloc first array member.
etc
Mark McIntyre
--
"Debugging is twice as hard as writing the code in the first place.
Therefore, if you write the code as cleverly as possible, you are,
by definition, not smart enough to debug it."
--Brian Kernighan
 
Reply With Quote
 
 
 
 
Eric Sosman
Guest
Posts: n/a
 
      04-21-2006


Yourko wrote On 04/21/06 20:37,:
> Hi there! I`me currently trying to write some simple programs in C.
> For one such program i created globals.h file. In that file i defined a structure of type _client, and a pointer of that type:
>
> struct _client{
> int fd; // file descriptor
> struct sockaddr_in sock_name;
> } * client;
>
> Later in that program i do:
> client = (struct _client *) malloc(sizeof(struct _client));


This is all right, but can be improved in a couple of
ways. First, you can get rid of the cast: it isn't needed,
it can prevent some compilers from issuing a helpful message
about failing to include <stdlib.h>, and it's even possible
for a mistaken cast to create an error where none existed
before. Second, replace `sizeof(struct _client)' with the
simpler `sizeof *client'. The advantage is that it's harder
to mis-match the pointer and the size, as in

struct message_header *header
= malloc(sizeof(struct message_header));
struct message_sender *sender
= malloc(sizeof(struct message_sender));
struct message_trailer *trailer
= malloc(sizeof(struct message_header));

With these two changes, you'd have

client = malloc(sizeof *client);

.... which is short, sweet, and the Officially Approved Way
to use malloc() and friends.

> and later:
> realloc(client, sizeof(struct _client);


I suspect you misunderstand realloc(). This does not
add another `sizeof(struct _client)' bytes to the memory
that `client' points to. Instead, it rearranges things so
the old memory area is replaced with a new one, possibly
larger or smaller. In this case you're asking for the same
size that the memory area already has, which is pointless.

Also, realloc() may need to move the memory to a new
location as part of the rearrangement. If it does so, the
old pointer is no longer useful: it points to the spot where
something used to be, not to the new spot the something now
occupies. realloc() returns a pointer to the new spot -- it
may be the same as the original, but you can't count on that.
You need to remember the returned pointer so you don't lose
track of the memory if realloc() moves it.

Assuming you're trying to add one more struct instance
to the allocated memory, so `client' now points to the first
of two adjacent instances, you'd use

client = realloc(client, 2 * sizeof *client);

(Note the rewriting of the `sizeof', as before.) But this is
still not quite right, because realloc() can fail (just as
malloc() can). If realloc() cannot come up with a big enough
piece of memory to satisfy your request, it does nothing and
returns NULL to let you know that it failed. Fine, you can
check `client' for NULL after the call -- but if it's NULL,
what then? If you're just going to issue an error message
and terminate the program, perhaps things are all right. But
if you're going to issue a message like "Sorry; can't handle
any more clients at the moment" and keep on running, you are
in trouble. Why? Because you no longer know where the original
memory is! You've just wiped out `client', your only pointer
to that memory, so you can't find the struct instance(s) that
existed before the failed realloc(). They still exist, but
you don't know where. This is known as a "memory leak."

The way to plug the leak is to store realloc()'s value in
a second pointer, check that pointer for NULL, and then only
overwrite `client' if you know realloc() succeeded:

struct _client *temp
= realloc(client, 2 * sizeof *client);
if (temp == NULL) {
issue_regretful_message();
return; /* or otherwise bail out */
}
/* Good! realloc() succeeded! */
client = temp;

> Here is my question: is my client pointer an array now? Can i now do:
> client[1]->fd = 3;


If you want the `fd' element of the second struct instance
in the allocated memory area, you can write any of

(client + 1)->fd = 3;
(*(client + 1)).fd = 3;
client[1].fd = 3;

The third form is recommended.

--
http://www.velocityreviews.com/forums/(E-Mail Removed)

 
Reply With Quote
 
 
 
 
Flash Gordon
Guest
Posts: n/a
 
      04-21-2006
Yourko wrote:
> Hi there! I`me currently trying to write some simple programs in C.
> For one such program i created globals.h file. In that file i defined a structure of type _client, and a pointer of that type:


Don't use names starting with underscores. Many of them are reserved in
many contexts and it's not worth the effort of remembering the few
instances where you are allowed to use them.

> struct _client{
> int fd; // file descriptor
> struct sockaddr_in sock_name;
> } * client;
>
> Later in that program i do:
> client = (struct _client *) malloc(sizeof(struct _client));


Don't cast the return value of malloc. It isn't required and can hide
serious problems from the compiler. The generally advised form around
here is:
ptr = malloc(N * sizeof *ptr);
Where N is the number of elements you want space for.

> and later:
> realloc(client, sizeof(struct _client);


That is still only enough space for 1 entry, and you seem to be throwing
away the pointer it returns!

Post complete real compilable code in future. It makes helping you easier.

> Here is my question: is my client pointer an array now? Can i now do:
> client[1]->fd = 3;
> for example?
> Compiler (gcc-3.3.6-linux-gnu) says no. But if so, how to do such things?


If you post a real complete small program showing the problem we might
be able to answer. Also, the exact error message is helpful rather than
just "it doesn't work" or similar statements.
--
Flash Gordon, living in interesting times.
Web site - http://home.flash-gordon.me.uk/
comp.lang.c posting guidelines and intro:
http://clc-wiki.net/wiki/Intro_to_clc

Inviato da X-Privat.Org - Registrazione gratuita http://www.x-privat.org/join.php
 
Reply With Quote
 
Michael Mair
Guest
Posts: n/a
 
      04-21-2006
Yourko schrieb:
> Hi there! I`me currently trying to write some simple programs in C.
> For one such program i created globals.h file. In that file i defined a structure of type _client, and a pointer of that type:
>
> struct _client{
> int fd; // file descriptor
> struct sockaddr_in sock_name;
> } * client;


Do not define objects or functions in headers unless you want to achieve
something specific[*].
Declare them in headers to "make them known" to every translation
unit directly or indirectly including this header.

I.e.
,-- globals.h -
#ifndef H_GLOBALS_H
#define H_GLOBALS_H
/* include whatever is necessary for struct sockaddr_in */
.....

struct _client{
int fd; // file descriptor
struct sockaddr_in sock_name;
};

extern struct _client *client;
.....
#endif
`----
,-- globals.c -
#include "globals.h"
#include <stddef.h>

struct _client *client = NULL;
.....
`----

This way, you have no structural problems at all -- otherwise,
your programme may exhibit some unexpected behaviour (or may not
link at all).
[*] If you have to define variables or functions in headers, it
is most of the time with internal linkage -- this is something
completely different. And even these definitions can be wrapped
into headers and be effectively "instantiated" outside of the
header


>
> Later in that program i do:
> client = (struct _client *) malloc(sizeof(struct _client));


The cast is unnecessary and may hide an error (forgetting to
#include <stdlib.h>); the "best practice" around here is
client = malloc(sizeof *client);

> and later:
> realloc(client, sizeof(struct _client);


You probably mean:
tmp = realloc(client, sizeof *client);
if (tmp == NULL) {
/* Handle error and do not continue below */
}
client = tmp;

> Here is my question: is my client pointer an array now? Can i now do:
> client[1]->fd = 3;
> for example?


1) No, a pointer never is an array. A pointer may point to an element
of an array. You allocated memory for a single struct _client instance,
so your pointer effectively grants you access to an array of one struct
_client.
2) No, for client[1] you would have needed to allocate enough memory
for at least two struct _client variables, e.g.
tmp = realloc(client, NumberOfClients * sizeof *client);
if (tmp == NULL) {
/* Handle error and do not continue below */
}
client = tmp;

If you have client pointing to storage sufficient to have more than
one struct _client object, then always accompany client by a size
telling how much "array elements" can be accessed via client.


Cheers
Michael
--
E-Mail: Mine is an /at/ gmx /dot/ de address.
 
Reply With Quote
 
Yourko
Guest
Posts: n/a
 
      04-22-2006
Hi there! I`me currently trying to write some simple programs in C.
For one such program i created globals.h file. In that file i defined a structure of type _client, and a pointer of that type:

struct _client{
int fd; // file descriptor
struct sockaddr_in sock_name;
} * client;

Later in that program i do:
client = (struct _client *) malloc(sizeof(struct _client));
and later:
realloc(client, sizeof(struct _client);

Here is my question: is my client pointer an array now? Can i now do:
client[1]->fd = 3;
for example?
Compiler (gcc-3.3.6-linux-gnu) says no. But if so, how to do such things?




---------------
"Software is like sex: it is better when it is free."
Linus Torvalds
 
Reply With Quote
 
Yourko
Guest
Posts: n/a
 
      04-22-2006
On Fri, 21 Apr 2006 23:21:39 +0100
Mark McIntyre <(E-Mail Removed)> wrote:

> On Sat, 22 Apr 2006 00:37:27 +0000, in comp.lang.c , Yourko
> <(E-Mail Removed)> wrote:
>
> >struct _client{
> > int fd; // file descriptor
> > struct sockaddr_in sock_name;
> >} * client;
> >
> >Later in that program i do:
> >client = (struct _client *) malloc(sizeof(struct _client));

>
> The cast is not necessary in C, and can conceal an error. Don't put it
> in.
>
> >and later:
> >realloc(client, sizeof(struct _client);
> >
> >Here is my question: is my client pointer an array now?

>
> No, you've just pointed "client" at some different block of memory. If
> you want an array, declare one.
>
> struct client ** pclient;
>
> pclient = malloc( 3* sizeof *pclient); // alloc pointers
> pclient[0] = malloc(sizeof *pclient[0]); // alloc first array member.
> etc
> Mark McIntyre
> --
> "Debugging is twice as hard as writing the code in the first place.
> Therefore, if you write the code as cleverly as possible, you are,
> by definition, not smart enough to debug it."
> --Brian Kernighan


Thanx, you helped me much!
Now i almost completely understand pointers, dynamic memory and arrays


---------------
"Software is like sex: it is better when it is free."
Linus Torvalds
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Can *common* struct-members of 2 different struct-types, that are thesame for the first common members, be accessed via pointer cast to either struct-type? John Reye C Programming 28 05-08-2012 12:24 AM
Struct inside a struct, annonymous? eselk@surfbest.net C++ 3 06-08-2006 04:11 PM
Struct inside a struct monkeydragon C++ 3 12-20-2005 05:36 PM
Access a control inside an usercontrol from another control inside another usercontrol nail ASP .Net 0 09-15-2004 03:55 PM
struct my_struct *p = (struct my_struct *)malloc(sizeof(struct my_struct)); Chris Fogelklou C Programming 36 04-20-2004 08:27 AM



Advertisments