Pointer to array of structs?

P

Paminu

Still having a few problems with malloc and pointers.

I have made a struct. Now I would like to make a pointer an array with 4
pointers to this struct.

#include <stdlib.h>
#include <stdio.h>
typedef struct _tnode_t {
void *content;
struct _tnode_t *kids;
} tnode_t;


int main(void)
{
tnode_t *array;
array = malloc(sizeof(tnode_t)*4);
array[3] = NULL;
return 0;

}

As I understand "array" point to the first element of an array consisting of
space for 4 tnode_t structs. But why can't I initialize element at index 3
to NULL?
 
A

Artie Gold

Paminu said:
Still having a few problems with malloc and pointers.

I have made a struct. Now I would like to make a pointer an array with 4
pointers to this struct.

#include <stdlib.h>
#include <stdio.h>
typedef struct _tnode_t {
void *content;
struct _tnode_t *kids;
} tnode_t;


int main(void)
{
tnode_t *array;
array = malloc(sizeof(tnode_t)*4);

Better (and that may further illustrate the point below)

array = malloc(sizeof *array * 4);

showing you that you have allocated enough space to point to 4 of what
your variable `array' points to.
array[3] = NULL;
return 0;

}

As I understand "array" point to the first element of an array consisting of
space for 4 tnode_t structs. But why can't I initialize element at index 3
to NULL?

Because array[3] is a `tnode_t', not a pointer to a `tnode_t' -- and
NULL is a pointer constant.

If you want an array of *pointers* to tnode_t, you would write:

tnode_t **array = malloc(sizeof *array * 4);

and allocate enough space for a tnode_t for each element as needed.

HTH,
--ag
 
R

Robert Gamble

Paminu said:
Still having a few problems with malloc and pointers.

I have made a struct. Now I would like to make a pointer an array with 4
pointers to this struct.

#include <stdlib.h>
#include <stdio.h>
typedef struct _tnode_t {
void *content;
struct _tnode_t *kids;
} tnode_t;


int main(void)
{
tnode_t *array;
array = malloc(sizeof(tnode_t)*4);
array[3] = NULL;
return 0;

}

As I understand "array" point to the first element of an array consisting of
space for 4 tnode_t structs. But why can't I initialize element at index 3
to NULL?

tnode_t *array; creates a pointer to a tnode_t structure. If you want
an array of 4 pointers to tnode_t structs you would use tnode_t
*array[4]. If you want want to create a dynamically allocated array of
pointers to tnode_t structures, you would want your pointer to be of
type "pointer to pointer to tnode_t":
tnode_t **array;

sizeof(tnode_t)*4 is the size required to store 4 tnode_t structures.
sizeof(tnode_t *)*4 will evaluate to the number of bytes required for 4
pointers to tnode_t.

Robert Gamble
 
P

Paminu

Robert said:
Paminu said:
Still having a few problems with malloc and pointers.

I have made a struct. Now I would like to make a pointer an array with 4
pointers to this struct.

#include <stdlib.h>
#include <stdio.h>
typedef struct _tnode_t {
void *content;
struct _tnode_t *kids;
} tnode_t;


int main(void)
{
tnode_t *array;
array = malloc(sizeof(tnode_t)*4);
array[3] = NULL;
return 0;

}

As I understand "array" point to the first element of an array consisting
of space for 4 tnode_t structs. But why can't I initialize element at
index 3 to NULL?

tnode_t *array; creates a pointer to a tnode_t structure. If you want
an array of 4 pointers to tnode_t structs you would use tnode_t
*array[4].


It seems to work if I do:

int main(void)
{
tnode_t *array[4];
tnode_t *test;
test = malloc(sizeof(tnode_t));
test->content = "Test";
test->kids = NULL;

array[0] = test;
array[1] = NULL;
// etc.

printf("%s\n", array[0]->content);

return 0;

}


was that what you meant?
 
P

Paminu

Robert said:
Paminu said:
Still having a few problems with malloc and pointers.

I have made a struct. Now I would like to make a pointer an array with 4
pointers to this struct.

#include <stdlib.h>
#include <stdio.h>
typedef struct _tnode_t {
void *content;
struct _tnode_t *kids;
} tnode_t;


int main(void)
{
tnode_t *array;
array = malloc(sizeof(tnode_t)*4);
array[3] = NULL;
return 0;

}

As I understand "array" point to the first element of an array consisting
of space for 4 tnode_t structs. But why can't I initialize element at
index 3 to NULL?

tnode_t *array; creates a pointer to a tnode_t structure.


Ok so it will only work if I set array[3] equal to a struct instead of a
pointer to a struct or NULL:

1)
tnode_t tt;
tt.content = "test";
tt.kids = NULL;
tnode_t *array;
array[0] = tt;


this seems to work and make sense. But if I make:

2)
int *p;
p = malloc(sizeof(int)*4);
p[0] = NULL;


this only give the warning: "warning: assignment makes integer from pointer
without a cast".

In 1) if I did: array[0] = NULL; I would get the error:

"error: incompatible types in assignment".

Why the different rules?
 
A

Antonio Contreras

Paminu said:
Robert said:
Paminu said:
Still having a few problems with malloc and pointers.

I have made a struct. Now I would like to make a pointer an array with 4
pointers to this struct.

#include <stdlib.h>
#include <stdio.h>
typedef struct _tnode_t {
void *content;
struct _tnode_t *kids;
} tnode_t;


int main(void)
{
tnode_t *array;
array = malloc(sizeof(tnode_t)*4);
array[3] = NULL;
return 0;

}

As I understand "array" point to the first element of an array consisting
of space for 4 tnode_t structs. But why can't I initialize element at
index 3 to NULL?

tnode_t *array; creates a pointer to a tnode_t structure.


Ok so it will only work if I set array[3] equal to a struct instead of a
pointer to a struct or NULL:

1)
tnode_t tt;
tt.content = "test";
tt.kids = NULL;
tnode_t *array;
array[0] = tt;


this seems to work and make sense. But if I make:

2)
int *p;
p = malloc(sizeof(int)*4);
p[0] = NULL;


this only give the warning: "warning: assignment makes integer from pointer
without a cast".

You still seem to be confusing pointers to types with the types they
point. In the second code snippet you posted you declare a pointer to
integer and then allocate memory for four integers and assign the value
returned by malloc to your pointer. Now you have a dynamic array of
four integers that can be accessed as p[0], p[1], [2] and p[3] or any
equivalent way.

In your next statement you assign a null pointer constant (NULL) to
p[0]. This can be done and is perfectly legal, but it is implementation
defined. Pointers can be implicitly or explicitly converted to integers
and back in an implementation defined manner. The compiler is just
being nice telling you that this is something strange.
In 1) if I did: array[0] = NULL; I would get the error:

"error: incompatible types in assignment".

Why the different rules?

Here the scenario is totally different. array is of type pointer to
tnode_t. array[0] is of type tnode_t which is a struct. Now you're
trying to assign a null pointer constant to a struct and this cannot be
done. There's no implicit conversion between pointers and structs and
if you think of it for a while you'll realize that there is no such
conversion because it simply doesn't make sense.

HTH
 
?

=?ISO-8859-1?Q?=22Nils_O=2E_Sel=E5sdal=22?=

Paminu said:
Still having a few problems with malloc and pointers.

I have made a struct. Now I would like to make a pointer an array with 4
pointers to this struct.

#include <stdlib.h>
#include <stdio.h>
typedef struct _tnode_t {
void *content;
struct _tnode_t *kids;
} tnode_t;


int main(void)
{
tnode_t *array;
array = malloc(sizeof(tnode_t)*4);
array[3] = NULL;
return 0;

}

As I understand "array" point to the first element of an array consisting of
space for 4 tnode_t structs. But why can't I initialize element at index 3
to NULL?

Because NULL is a pointer value. index 3 stores a tnode_t , not a
pointer to a tnode_t.

You cannot store a pointer in a place that cannot hold a pointer.
 
R

Rod Pemberton

Paminu said:
Robert said:
Paminu said:
Still having a few problems with malloc and pointers.

I have made a struct. Now I would like to make a pointer an array with 4
pointers to this struct.

#include <stdlib.h>
#include <stdio.h>
typedef struct _tnode_t {
void *content;
struct _tnode_t *kids;
} tnode_t;


int main(void)
{
tnode_t *array;
array = malloc(sizeof(tnode_t)*4);
array[3] = NULL;
return 0;

}

As I understand "array" point to the first element of an array consisting
of space for 4 tnode_t structs. But why can't I initialize element at
index 3 to NULL?

tnode_t *array; creates a pointer to a tnode_t structure.


Ok so it will only work if I set array[3] equal to a struct instead of a
pointer to a struct or NULL:

1)
tnode_t tt;
tt.content = "test";
tt.kids = NULL;
tnode_t *array;
array[0] = tt;


this seems to work and make sense. But if I make:

2)
int *p;
p = malloc(sizeof(int)*4);
p[0] = NULL;


this only give the warning: "warning: assignment makes integer from pointer
without a cast".

In 1) if I did: array[0] = NULL; I would get the error:

"error: incompatible types in assignment".

Why the different rules?

Different errors.

The pointer to an int, p, can be assigned NULL:
p=NULL;

Or, you can assign the int that p[0] references to zero:
p[0]=0;

Or, you can assign the int that p[1] references to zero:
p[1]=0;

etc...

When you write:
p[0] = NULL;
You are attempting to convert a pointer (NULL) to an int.


Rod Pemberton
 
P

Paminu

Nils O. Selåsdal said:
Paminu said:
Still having a few problems with malloc and pointers.

I have made a struct. Now I would like to make a pointer an array with 4
pointers to this struct.

#include <stdlib.h>
#include <stdio.h>
typedef struct _tnode_t {
void *content;
struct _tnode_t *kids;
} tnode_t;


int main(void)
{
tnode_t *array;
array = malloc(sizeof(tnode_t)*4);
array[3] = NULL;
return 0;

}

As I understand "array" point to the first element of an array consisting
of space for 4 tnode_t structs. But why can't I initialize element at
index 3 to NULL?

Because NULL is a pointer value. index 3 stores a tnode_t , not a
pointer to a tnode_t.

You cannot store a pointer in a place that cannot hold a pointer.


Ok I guess that this is correct and identical:

typedef struct _tnode_t {
void *content;
struct _tnode_t *kids;
} tnode_t;

int main(void)
{
tnode_t *array;
array[0].kids = NULL;
array->kids = NULL;
return 0;

}

when I do this: array I get a struct. When I do this: array->kids I get a
pointer to a struct.
 
A

Antonio Contreras

Paminu wrote:

....snip...
Ok I guess that this is correct and identical:

typedef struct _tnode_t {
void *content;
struct _tnode_t *kids;
} tnode_t;

int main(void)
{
tnode_t *array;
array[0].kids = NULL;
array->kids = NULL;
return 0;

}

when I do this: array I get a struct. When I do this: array->kids I get a
pointer to a struct.


There's still an issue, you've declared a pointer to a struct, but you
have not initialized it to a valid value (through a call to
malloc/calloc). Your program is dereferencing a pointer that doesn't
point to a valid block of memory and so invokes undefined behaviour.
 
B

Barry Schwarz

Robert said:
Paminu said:
Still having a few problems with malloc and pointers.

I have made a struct. Now I would like to make a pointer an array with 4
pointers to this struct.

#include <stdlib.h>
#include <stdio.h>
typedef struct _tnode_t {
void *content;
struct _tnode_t *kids;
} tnode_t;


int main(void)
{
tnode_t *array;
array = malloc(sizeof(tnode_t)*4);
array[3] = NULL;
return 0;

}

As I understand "array" point to the first element of an array consisting
of space for 4 tnode_t structs. But why can't I initialize element at
index 3 to NULL?

tnode_t *array; creates a pointer to a tnode_t structure.


Ok so it will only work if I set array[3] equal to a struct instead of a
pointer to a struct or NULL:

1)
tnode_t tt;
tt.content = "test";
tt.kids = NULL;
tnode_t *array;
array[0] = tt;

tt is a tnode_t. array is a pointer to a tnode_t. array is not
initialized to point anywhere. array[0] would be the first tnode_t it
pointed if it did point anywhere. That is why your program is
syntactically correct. Some compilers warn you if you attempt to use
an uninitialized variable but even without the warning it is still
undefined behavior. If you added a call to malloc before using
array[0], array would then point to one or more structures and the
assignment would be fine.
this seems to work and make sense. But if I make:

Seeming to work is just leading down the path of murphy's law.
2)
int *p;
p = malloc(sizeof(int)*4);
p[0] = NULL;


this only give the warning: "warning: assignment makes integer from pointer
without a cast".

p is a pointer to int. p[0] is the first uninitialized int it points
to. NULL is not a suitable value for int. Hence the warning. Do not
think of it as "only". Your program is doing something much different
than you expect.
In 1) if I did: array[0] = NULL; I would get the error:

"error: incompatible types in assignment".

There is an implementation defined conversion from void* (the type of
NULL) to int. There is no such conversion from int* to struct.
Why the different rules?

Different types.


Remove del for email
 
R

Roka100

Hi,
I have to say another problem that do not forget to free() them when
you allocated a pointer. Maybe there are no errors ,but that will cause
memory leak . ( Maybe your OS is stronger than mine :)
 
V

Vladimir S. Oka

Hi,
I have to say another problem that do not forget to free() them when
you allocated a pointer. Maybe there are no errors ,but that will cause
memory leak . ( Maybe your OS is stronger than mine :)

What are you talking about? Who, or what are "them"? Etc...

Please quote what and who you're replying to. Read this:

"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/>
 
R

Roka100

Thanks for mentioning.
I am sorry about that, I am new here.
And I will pay attention to that.
 
V

Vladimir S. Oka

Thanks for mentioning.
I am sorry about that, I am new here.
And I will pay attention to that.

Good, thank you. Also, don't top-post.

--
BR, Vladimir

43rd Law of Computing:
Anything that can go wr
fortune: Segmentation violation -- Core dumped
 
D

Dave Thompson

Ok I guess that this is correct and identical:

typedef struct _tnode_t {
void *content;
struct _tnode_t *kids;
} tnode_t;
Most identifiers beginning with underscore are reserved to the
implementation and you shouldn't use them. This reservation is not
always enforced, indeed rarely is, but you are just asking for trouble
sometime in the future when it will be (maximally) incovenient. (There
are a few categories that are allowed, but your case here is not one
of them, and rather than remember the exact rules it's easier to avoid
all of them.)

Note it is perfectly legal to use the same identifier for the struct
tag and the typedef-name; they are in separate namespaces. If you
don't wish to, and do want to have both, the usual practice is to put
a suffix on one, either like typedef struct tnode { ... } tnode_t;
or like typedef struct tnode_s { ... } tnode;
int main(void)
{
tnode_t *array;
array[0].kids = NULL;
array->kids = NULL;

Yes. Given that the type is defined correctly (and as another reply
points out the pointer is initialized validly), then:
p -> e is defined as (*p) . e
p[0] is the same as *p
p[0] . e is the same as (*p) . e
return 0;

}

when I do this: array I get a struct. When I do this: array->kids I get a
pointer to a struct.


But note that if array is actually an array, as the name implies,
array allows you to access elements other than array[0], and
array.kids gives you the pointer in the i'th element. array->kids
gives you always and only array[0].kids.


- David.Thompson1 at worldnet.att.net
 

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,982
Messages
2,570,186
Members
46,739
Latest member
Clint8040

Latest Threads

Top