473,385 Members | 1,873 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,385 software developers and data experts.

C beginner: struct inside another struct...

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
Apr 21 '06 #1
5 5285
On Sat, 22 Apr 2006 00:37:27 +0000, in comp.lang.c , Yourko
<jb**@icmail.net> 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
Apr 21 '06 #2


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.

--
Er*********@sun.com

Apr 21 '06 #3
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.
Apr 21 '06 #4
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
Apr 21 '06 #5
On Fri, 21 Apr 2006 23:21:39 +0100
Mark McIntyre <ma**********@spamcop.net> wrote:
On Sat, 22 Apr 2006 00:37:27 +0000, in comp.lang.c , Yourko
<jb**@icmail.net> 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
Apr 22 '06 #6

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

5
by: uny ternally | last post by:
I was experimenting in Visual C++ and ran into the following problem. I have the struct listed below. I also have a function that passes a variable of the struct type by reference and set the...
1
by: Bryan Parkoff | last post by:
I know how to write "Pointer to Function" inside struct or class without using static, but I have decided to add static to all functions inside struct or class because I want member functions to be...
20
by: Elliot Marks | last post by:
If a struct or its members are passed to a function, must it be declared globally? #include <stdio.h> struct mystruct{ int a; int b; }; int structfunc(struct mystruct foo);
6
by: sathyashrayan | last post by:
#include<stdio.h> #include<stdlib.h> #include<string.h> struct tree { int data; struct tree *left,*right; }; void init(struct tree *node)
1
by: Jón Sveinsson | last post by:
Hello everone I have code from c which I need to convert to c#, the c code is following, as you can see there is a struct inside struct typedef struct { some variables....
6
by: Michael C | last post by:
Is it possible to use an ArrayList inside a struct? I keep running into a null reference exception when I try to Add to the ArrayList in the struct, and it won't let me initialize the ArrayList in...
6
by: CptDondo | last post by:
I'm trying to figure out some code that uses structures, structures, and more structures... It's a bit of rat's nest, and I'm having some trouble sorting it all out. The authors use a lot of...
12
by: djhong | last post by:
Following is a snippet of a header file. Here, #define are inside struct evConn{} Any advantage of putting them inside struct block? Looks like there is no diff in scoping of each...
3
by: dreiko466 | last post by:
(sorry about my english...) I am a newbie in C (3 month expierience) I have wrote a simple test programm in VS2005, what i do wrong?Please... In this programm i create a double linked list.Then ...
1
by: CloudSolutions | last post by:
Introduction: For many beginners and individual users, requiring a credit card and email registration may pose a barrier when starting to use cloud servers. However, some cloud server providers now...
0
by: Faith0G | last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.