469,134 Members | 1,315 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 469,134 developers. It's quick & easy.

Array of pointers in a struct

fix
Hi all,
I feel unclear about what my code is doing, although it works but I am
not sure if there is any possible bug, please help me to verify it.
This is a trie node (just similar to tree nodes) struct, I am storing an
array of 27 pointers and a void pointer that can point to anything.
typedef struct trieNode
{
struct trieNode *children[27]; // The children nodes
void *obj; // The object stored
} TrieNode;

And this is the code I make a new trie node, initialize and return it.
TrieNode *newTrieNode()
{
int i;
// Allocate memory for the node
TrieNode *node = (TrieNode *)malloc(sizeof(TrieNode));
// points the object to NULL
node->obj = NULL;
// **********
*(node->children) = (TrieNode *)malloc(sizeof(TrieNode *) * 27);
// Set all pointers in the children array to NULL
for (i = 0; i < 27; i++)
node->children[i] = NULL;
return node;
}
The problem comes from the line below the asterisks.
Initially I have coded
node->children = (TrieNode **)malloc(sizeof(TrieNode *) * 27);
but the compiler does not let me compile.
When I change it to the one now, it works, but it seems a bit unnatural
to me. children is a pointer to pointer right? Does *children or
children[0] have to be initialized by me?
Thanks.
fix.

Nov 14 '05 #1
20 2564
fix wrote:
Hi all,
I feel unclear about what my code is doing, although it works but I am
not sure if there is any possible bug, please help me to verify it.
This is a trie node (just similar to tree nodes) struct, I am storing an
array of 27 pointers and a void pointer that can point to anything.
typedef struct trieNode
{
struct trieNode *children[27]; // The children nodes
void *obj; // The object stored
} TrieNode;

And this is the code I make a new trie node, initialize and return it.
TrieNode *newTrieNode()
{
int i;
// Allocate memory for the node
TrieNode *node = (TrieNode *)malloc(sizeof(TrieNode)); This has been beaten to death. This cast is not necessary - Do this
necessary.

TrieNode *node = malloc(sizeof(TrieNode));.
// points the object to NULL
node->obj = NULL;
// **********
*(node->children) = (TrieNode *)malloc(sizeof(TrieNode *) * 27);


Whatz this line doing here . I dont understand the significance.
What is your objective here ?

--
Karthik
Humans please 'removeme_' for my real email.
Nov 14 '05 #2
fix wrote:
Hi all,
I feel unclear about what my code is doing, although it works but I am
not sure if there is any possible bug, please help me to verify it.
This is a trie node (just similar to tree nodes) struct, I am storing an
array of 27 pointers and a void pointer that can point to anything.
typedef struct trieNode
{
struct trieNode *children[27]; // The children nodes
void *obj; // The object stored
} TrieNode;

And this is the code I make a new trie node, initialize and return it.
TrieNode *newTrieNode()
{
int i;
// Allocate memory for the node
TrieNode *node = (TrieNode *)malloc(sizeof(TrieNode)); This has been beaten to death. This cast is not necessary - Do this
necessary.

TrieNode *node = malloc(sizeof(TrieNode));.
// points the object to NULL
node->obj = NULL;
// **********
*(node->children) = (TrieNode *)malloc(sizeof(TrieNode *) * 27);


Whatz this line doing here . I dont understand the significance.
What is your objective here ?

--
Karthik
Humans please 'removeme_' for my real email.
Nov 14 '05 #3
On Fri, 30 Apr 2004 20:47:47 -0500, fix <fi*@here.com> wrote:
Hi all,
I feel unclear about what my code is doing, although it works but I am
not sure if there is any possible bug, please help me to verify it.
This is a trie node (just similar to tree nodes) struct, I am storing an
array of 27 pointers and a void pointer that can point to anything.
typedef struct trieNode
{
struct trieNode *children[27]; // The children nodes
This is an array of 27 pointers.
void *obj; // The object stored
} TrieNode;

And this is the code I make a new trie node, initialize and return it.
TrieNode *newTrieNode()
{
int i;
// Allocate memory for the node
TrieNode *node = (TrieNode *)malloc(sizeof(TrieNode));
Don't cast the return from malloc. It doesn't help and can prevent
the compiler from warning you that you forgot to include stdlib.h.
Such an omission would lead to undefined behavior.
// points the object to NULL
node->obj = NULL;
// **********
*(node->children) = (TrieNode *)malloc(sizeof(TrieNode *) * 27);
This is a problem. Work through the types.

node is a pointer to struct.
node->children is an array of 27 pointers to struct.
*(node->children) is exactly equivalent to (node->children)[0]
which is the first element of that array. This element is obviously a
pointer to struct.
The space you allocate is not sufficient to hold such a struct.
The struct consists of 27 struct pointers plus a void pointer plus any
padding. You allocate only enough space for the 27 struct pointers.
At this point you have committed the unpardonable sin of lying to
the compiler. You have told it that node->children[0] will point to
a struct and it doesn't.

On top of all that, you don't need this code. The struct already
contains an array of 27 pointers so you don't need another set.
// Set all pointers in the children array to NULL
for (i = 0; i < 27; i++)
node->children[i] = NULL;
The first time through the loop, you destroy the value in
node->children[0] that you set in the previous malloc. This causes a
memory leak because you can never recover the original address to free
the memory.
return node;
}
The problem comes from the line below the asterisks.
Initially I have coded
node->children = (TrieNode **)malloc(sizeof(TrieNode *) * 27);
Work through the types as above. node->children is an array. An
unsubscripted array may not appear on the left of an assignment
statement. (It is not a modifiable lvalue.)

As noted above you don't need this either. node->children already
contains enough space to hold 27 pointers to struct.
but the compiler does not let me compile.
When I change it to the one now, it works, but it seems a bit unnatural
to me. children is a pointer to pointer right? Does *children or
children[0] have to be initialized by me?


Yes. In your very first malloc (the one just with node), you allocate
space to hold the struct. The struct consists of 28 variables, 27
pointers to struct and 1 pointer to void. You must initialize each of
these variables before it is evaluated. That means children[0],
children[1], ..., children[26]. You do initialize the pointer to void
above.

When you do initialize one of the children, it must be with NULL or
with the address of a struct (or dynamically allocated memory large
enough to hold a struct).

<<Remove the del for email>>
Nov 14 '05 #4
fix


Barry Schwarz wrote:
struct trieNode *children[27]; // The children nodes

This is an array of 27 pointers.


Yes.
And this is the code I make a new trie node, initialize and return it.
TrieNode *newTrieNode()
{
int i;
// Allocate memory for the node
TrieNode *node = (TrieNode *)malloc(sizeof(TrieNode));

Don't cast the return from malloc. It doesn't help and can prevent
the compiler from warning you that you forgot to include stdlib.h.
Such an omission would lead to undefined behavior.


I did read post about this problem. I would like to omit it if possible.
Well I am using VS.NET to write the programs, test and compile, if I
cast it, there's a warning, if I don't, there isn't.
But the problem is, these programs are assignment of my computer science
class, and the prof said that I have to make sure it works on gcc. gcc
does give me error if I don't cast:
warning: initialization makes pointer from integer without a cast
if I cast, it doesn't give me this.
I did turn in my first C program without any cast, I got marks deduced.
// **********
*(node->children) = (TrieNode *)malloc(sizeof(TrieNode *) * 27);

This is a problem. Work through the types.

node is a pointer to struct.
node->children is an array of 27 pointers to struct.
*(node->children) is exactly equivalent to (node->children)[0]
which is the first element of that array. This element is obviously a
pointer to struct.
The space you allocate is not sufficient to hold such a struct.
The struct consists of 27 struct pointers plus a void pointer plus any
padding. You allocate only enough space for the 27 struct pointers.
At this point you have committed the unpardonable sin of lying to
the compiler. You have told it that node->children[0] will point to
a struct and it doesn't.

On top of all that, you don't need this code. The struct already
contains an array of 27 pointers so you don't need another set.


Hm...... I am not that clear about what I learnt. A var[] and *var can
be used interchangeably, but what's the difference? Does the compiler
allocate space for var[] but not *var?
// Set all pointers in the children array to NULL
for (i = 0; i < 27; i++)
node->children[i] = NULL;

The first time through the loop, you destroy the value in
node->children[0] that you set in the previous malloc. This causes a
memory leak because you can never recover the original address to free
the memory.


Well actually if I don't free() the memory I allocated, will the memory
be free after the program quits?
return node;
}
The problem comes from the line below the asterisks.
Initially I have coded
node->children = (TrieNode **)malloc(sizeof(TrieNode *) * 27);

Work through the types as above. node->children is an array. An
unsubscripted array may not appear on the left of an assignment
statement. (It is not a modifiable lvalue.)


Oh that's the error when I compiled. "left operand must be l-value", I
didn't really understand what it means.
As noted above you don't need this either. node->children already
contains enough space to hold 27 pointers to struct.

but the compiler does not let me compile.
When I change it to the one now, it works, but it seems a bit unnatural
to me. children is a pointer to pointer right? Does *children or
children[0] have to be initialized by me?

Yes. In your very first malloc (the one just with node), you allocate
space to hold the struct. The struct consists of 28 variables, 27
pointers to struct and 1 pointer to void. You must initialize each of
these variables before it is evaluated. That means children[0],
children[1], ..., children[26]. You do initialize the pointer to void
above.

When you do initialize one of the children, it must be with NULL or
with the address of a struct (or dynamically allocated memory large
enough to hold a struct).


So I did right in the for-loop?

Nov 14 '05 #5
On Fri, 30 Apr 2004 20:47:47 -0500, fix <fi*@here.com> wrote:
Hi all,
I feel unclear about what my code is doing, although it works but I am
not sure if there is any possible bug, please help me to verify it.
This is a trie node (just similar to tree nodes) struct, I am storing an
array of 27 pointers and a void pointer that can point to anything.
typedef struct trieNode
{
struct trieNode *children[27]; // The children nodes
This is an array of 27 pointers.
void *obj; // The object stored
} TrieNode;

And this is the code I make a new trie node, initialize and return it.
TrieNode *newTrieNode()
{
int i;
// Allocate memory for the node
TrieNode *node = (TrieNode *)malloc(sizeof(TrieNode));
Don't cast the return from malloc. It doesn't help and can prevent
the compiler from warning you that you forgot to include stdlib.h.
Such an omission would lead to undefined behavior.
// points the object to NULL
node->obj = NULL;
// **********
*(node->children) = (TrieNode *)malloc(sizeof(TrieNode *) * 27);
This is a problem. Work through the types.

node is a pointer to struct.
node->children is an array of 27 pointers to struct.
*(node->children) is exactly equivalent to (node->children)[0]
which is the first element of that array. This element is obviously a
pointer to struct.
The space you allocate is not sufficient to hold such a struct.
The struct consists of 27 struct pointers plus a void pointer plus any
padding. You allocate only enough space for the 27 struct pointers.
At this point you have committed the unpardonable sin of lying to
the compiler. You have told it that node->children[0] will point to
a struct and it doesn't.

On top of all that, you don't need this code. The struct already
contains an array of 27 pointers so you don't need another set.
// Set all pointers in the children array to NULL
for (i = 0; i < 27; i++)
node->children[i] = NULL;
The first time through the loop, you destroy the value in
node->children[0] that you set in the previous malloc. This causes a
memory leak because you can never recover the original address to free
the memory.
return node;
}
The problem comes from the line below the asterisks.
Initially I have coded
node->children = (TrieNode **)malloc(sizeof(TrieNode *) * 27);
Work through the types as above. node->children is an array. An
unsubscripted array may not appear on the left of an assignment
statement. (It is not a modifiable lvalue.)

As noted above you don't need this either. node->children already
contains enough space to hold 27 pointers to struct.
but the compiler does not let me compile.
When I change it to the one now, it works, but it seems a bit unnatural
to me. children is a pointer to pointer right? Does *children or
children[0] have to be initialized by me?


Yes. In your very first malloc (the one just with node), you allocate
space to hold the struct. The struct consists of 28 variables, 27
pointers to struct and 1 pointer to void. You must initialize each of
these variables before it is evaluated. That means children[0],
children[1], ..., children[26]. You do initialize the pointer to void
above.

When you do initialize one of the children, it must be with NULL or
with the address of a struct (or dynamically allocated memory large
enough to hold a struct).

<<Remove the del for email>>
Nov 14 '05 #6
fix


Barry Schwarz wrote:
struct trieNode *children[27]; // The children nodes

This is an array of 27 pointers.


Yes.
And this is the code I make a new trie node, initialize and return it.
TrieNode *newTrieNode()
{
int i;
// Allocate memory for the node
TrieNode *node = (TrieNode *)malloc(sizeof(TrieNode));

Don't cast the return from malloc. It doesn't help and can prevent
the compiler from warning you that you forgot to include stdlib.h.
Such an omission would lead to undefined behavior.


I did read post about this problem. I would like to omit it if possible.
Well I am using VS.NET to write the programs, test and compile, if I
cast it, there's a warning, if I don't, there isn't.
But the problem is, these programs are assignment of my computer science
class, and the prof said that I have to make sure it works on gcc. gcc
does give me error if I don't cast:
warning: initialization makes pointer from integer without a cast
if I cast, it doesn't give me this.
I did turn in my first C program without any cast, I got marks deduced.
// **********
*(node->children) = (TrieNode *)malloc(sizeof(TrieNode *) * 27);

This is a problem. Work through the types.

node is a pointer to struct.
node->children is an array of 27 pointers to struct.
*(node->children) is exactly equivalent to (node->children)[0]
which is the first element of that array. This element is obviously a
pointer to struct.
The space you allocate is not sufficient to hold such a struct.
The struct consists of 27 struct pointers plus a void pointer plus any
padding. You allocate only enough space for the 27 struct pointers.
At this point you have committed the unpardonable sin of lying to
the compiler. You have told it that node->children[0] will point to
a struct and it doesn't.

On top of all that, you don't need this code. The struct already
contains an array of 27 pointers so you don't need another set.


Hm...... I am not that clear about what I learnt. A var[] and *var can
be used interchangeably, but what's the difference? Does the compiler
allocate space for var[] but not *var?
// Set all pointers in the children array to NULL
for (i = 0; i < 27; i++)
node->children[i] = NULL;

The first time through the loop, you destroy the value in
node->children[0] that you set in the previous malloc. This causes a
memory leak because you can never recover the original address to free
the memory.


Well actually if I don't free() the memory I allocated, will the memory
be free after the program quits?
return node;
}
The problem comes from the line below the asterisks.
Initially I have coded
node->children = (TrieNode **)malloc(sizeof(TrieNode *) * 27);

Work through the types as above. node->children is an array. An
unsubscripted array may not appear on the left of an assignment
statement. (It is not a modifiable lvalue.)


Oh that's the error when I compiled. "left operand must be l-value", I
didn't really understand what it means.
As noted above you don't need this either. node->children already
contains enough space to hold 27 pointers to struct.

but the compiler does not let me compile.
When I change it to the one now, it works, but it seems a bit unnatural
to me. children is a pointer to pointer right? Does *children or
children[0] have to be initialized by me?

Yes. In your very first malloc (the one just with node), you allocate
space to hold the struct. The struct consists of 28 variables, 27
pointers to struct and 1 pointer to void. You must initialize each of
these variables before it is evaluated. That means children[0],
children[1], ..., children[26]. You do initialize the pointer to void
above.

When you do initialize one of the children, it must be with NULL or
with the address of a struct (or dynamically allocated memory large
enough to hold a struct).


So I did right in the for-loop?

Nov 14 '05 #7
On Sat, 01 May 2004 01:19:14 -0500, in comp.lang.c , fix <fi*@here.com>
wrote:
Don't cast the return from malloc. It doesn't help and can prevent
the compiler from warning you that you forgot to include stdlib.h.
Such an omission would lead to undefined behavior.
But the problem is, these programs are assignment of my computer science
class, and the prof said that I have to make sure it works on gcc. gcc
does give me error if I don't cast:


This is eactly why you _do not_ cast. The warning is to tell you that you
are doing something wrong. In this case, you have not included the header
that prototypes malloc. The result is that your code is seriously
defective, and may even crash.
warning: initialization makes pointer from integer without a cast
This is a serious warning. DO NOT HIDE WARNINGS WITH CASTS until you know
precisely what you're doing !
if I cast, it doesn't give me this.


Because then you are saying to the compiler "Yes, I want to turn an integer
into a pointer, even though it is meaningless and produces garbage"

--
Mark McIntyre
CLC FAQ <http://www.eskimo.com/~scs/C-faq/top.html>
CLC readme: <http://www.angelfire.com/ms3/bchambless0/welcome_to_clc.html>
----== Posted via Newsfeed.Com - Unlimited-Uncensored-Secure Usenet News==----
http://www.newsfeed.com The #1 Newsgroup Service in the World! >100,000 Newsgroups
---= 19 East/West-Coast Specialized Servers - Total Privacy via Encryption =---
Nov 14 '05 #8
On Sat, 01 May 2004 01:19:14 -0500, fix <fi*@here.com> wrote:


Barry Schwarz wrote:
struct trieNode *children[27]; // The children nodes

This is an array of 27 pointers.


Yes.
And this is the code I make a new trie node, initialize and return it.
TrieNode *newTrieNode()
{
int i;
// Allocate memory for the node
TrieNode *node = (TrieNode *)malloc(sizeof(TrieNode));

Don't cast the return from malloc. It doesn't help and can prevent
the compiler from warning you that you forgot to include stdlib.h.
Such an omission would lead to undefined behavior.


I did read post about this problem. I would like to omit it if possible.
Well I am using VS.NET to write the programs, test and compile, if I
cast it, there's a warning, if I don't, there isn't.


Go back and read my original comment. Did you include stdlib.h?
But the problem is, these programs are assignment of my computer science
class, and the prof said that I have to make sure it works on gcc. gcc
does give me error if I don't cast:
warning: initialization makes pointer from integer without a cast
if I cast, it doesn't give me this.
This is exactly the warning you need to avoid undefined behavior. The
warning tells you the compiler thinks malloc is returning an integer.
Since you know malloc returns a pointer to void, the question is why
does the compiler think this? The answer is because you never told
the compiler what malloc really did. The reason you never told it is
because you forgot to include stdlib.h which contains the prototype
for malloc.

I don't know anything about gcc or your hardware but consider the case
where returned pointers and returned integers use different hardware
registers. The cast shuts up the warning without solving the problem.
All the cast does is tell the compiler to generate code that takes the
supposed integer return from malloc and convert it without warning to
a pointer. Since malloc doesn't return an integer, this still makes
no sense.
I did turn in my first C program without any cast, I got marks deduced.
If you turned in a program with warnings, what do you expect.
// **********
*(node->children) = (TrieNode *)malloc(sizeof(TrieNode *) * 27);

This is a problem. Work through the types.

node is a pointer to struct.
node->children is an array of 27 pointers to struct.
*(node->children) is exactly equivalent to (node->children)[0]
which is the first element of that array. This element is obviously a
pointer to struct.
The space you allocate is not sufficient to hold such a struct.
The struct consists of 27 struct pointers plus a void pointer plus any
padding. You allocate only enough space for the 27 struct pointers.
At this point you have committed the unpardonable sin of lying to
the compiler. You have told it that node->children[0] will point to
a struct and it doesn't.

On top of all that, you don't need this code. The struct already
contains an array of 27 pointers so you don't need another set.


Hm...... I am not that clear about what I learnt. A var[] and *var can
be used interchangeably, but what's the difference? Does the compiler
allocate space for var[] but not *var?


NO NO NO NO. A var[] is an array. A *var is a pointer. While they
share a certain amount of common syntax using subscript notation they
are by no means interchangeable. Read the faq. Look in your text.
Google through the archives for postings that talk about pointers and
arrays, especially those by CBFalconer.

And for heaven's sake, don't say this to your instructor. The only
possible result is bad. Either he will downgrade you for not
understanding a basic aspect of the language or he will agree with you
and you will know he is incompetent and you have wasted a semester.
// Set all pointers in the children array to NULL
for (i = 0; i < 27; i++)
node->children[i] = NULL;

The first time through the loop, you destroy the value in
node->children[0] that you set in the previous malloc. This causes a
memory leak because you can never recover the original address to free
the memory.


Well actually if I don't free() the memory I allocated, will the memory
be free after the program quits?


And you believe this is an excuse to write sloppy code?
return node;
}
The problem comes from the line below the asterisks.
Initially I have coded
node->children = (TrieNode **)malloc(sizeof(TrieNode *) * 27);

Work through the types as above. node->children is an array. An
unsubscripted array may not appear on the left of an assignment
statement. (It is not a modifiable lvalue.)


Oh that's the error when I compiled. "left operand must be l-value", I
didn't really understand what it means.
As noted above you don't need this either. node->children already
contains enough space to hold 27 pointers to struct.

but the compiler does not let me compile.
When I change it to the one now, it works, but it seems a bit unnatural
to me. children is a pointer to pointer right? Does *children or
children[0] have to be initialized by me?

Yes. In your very first malloc (the one just with node), you allocate
space to hold the struct. The struct consists of 28 variables, 27
pointers to struct and 1 pointer to void. You must initialize each of
these variables before it is evaluated. That means children[0],
children[1], ..., children[26]. You do initialize the pointer to void
above.

When you do initialize one of the children, it must be with NULL or
with the address of a struct (or dynamically allocated memory large
enough to hold a struct).


So I did right in the for-loop?


Depends on why you want an array of 27 NULL pointers.
<<Remove the del for email>>
Nov 14 '05 #9
Barry Schwarz wrote:
On Sat, 01 May 2004 01:19:14 -0500, fix <fi*@here.com> wrote:

.... snip ...

Hm...... I am not that clear about what I learnt. A var[] and
*var can be used interchangeably, but what's the difference?
Does the compiler allocate space for var[] but not *var?


NO NO NO NO. A var[] is an array. A *var is a pointer. While
they share a certain amount of common syntax using subscript
notation they are by no means interchangeable. Read the faq.
Look in your text. Google through the archives for postings that
talk about pointers and arrays, especially those by CBFalconer.


I think you mean Chris Torek :-) Look for 'the rule'.

--
A: Because it fouls the order in which people normally read text.
Q: Why is top-posting such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?

Nov 14 '05 #10
fix

Barry Schwarz wrote:
And this is the code I make a new trie node, initialize and return it.
TrieNode *newTrieNode()
{
int i;
// Allocate memory for the node
TrieNode *node = (TrieNode *)malloc(sizeof(TrieNode));
Don't cast the return from malloc. It doesn't help and can prevent
the compiler from warning you that you forgot to include stdlib.h.
Such an omission would lead to undefined behavior.


I did read post about this problem. I would like to omit it if possible.
Well I am using VS.NET to write the programs, test and compile, if I
cast it, there's a warning, if I don't, there isn't.

Go back and read my original comment. Did you include stdlib.h?


OK, I didn't. But why does my program can still use malloca?
But the problem is, these programs are assignment of my computer science
class, and the prof said that I have to make sure it works on gcc. gcc
does give me error if I don't cast:
warning: initialization makes pointer from integer without a cast
if I cast, it doesn't give me this.

This is exactly the warning you need to avoid undefined behavior. The
warning tells you the compiler thinks malloc is returning an integer.
Since you know malloc returns a pointer to void, the question is why
does the compiler think this? The answer is because you never told
the compiler what malloc really did. The reason you never told it is
because you forgot to include stdlib.h which contains the prototype
for malloc.

I don't know anything about gcc or your hardware but consider the case
where returned pointers and returned integers use different hardware
registers. The cast shuts up the warning without solving the problem.
All the cast does is tell the compiler to generate code that takes the
supposed integer return from malloc and convert it without warning to
a pointer. Since malloc doesn't return an integer, this still makes
no sense.

I did turn in my first C program without any cast, I got marks deduced.

If you turned in a program with warnings, what do you expect.

// **********
*(node->children) = (TrieNode *)malloc(sizeof(TrieNode *) * 27);
This is a problem. Work through the types.

node is a pointer to struct.
node->children is an array of 27 pointers to struct.
*(node->children) is exactly equivalent to (node->children)[0]
which is the first element of that array. This element is obviously a
pointer to struct.
The space you allocate is not sufficient to hold such a struct.
The struct consists of 27 struct pointers plus a void pointer plus any
padding. You allocate only enough space for the 27 struct pointers.
At this point you have committed the unpardonable sin of lying to
the compiler. You have told it that node->children[0] will point to
a struct and it doesn't.

On top of all that, you don't need this code. The struct already
contains an array of 27 pointers so you don't need another set.


Hm...... I am not that clear about what I learnt. A var[] and *var can
be used interchangeably, but what's the difference? Does the compiler
allocate space for var[] but not *var?

NO NO NO NO. A var[] is an array. A *var is a pointer. While they
share a certain amount of common syntax using subscript notation they
are by no means interchangeable. Read the faq. Look in your text.
Google through the archives for postings that talk about pointers and
arrays, especially those by CBFalconer.

And for heaven's sake, don't say this to your instructor. The only
possible result is bad. Either he will downgrade you for not
understanding a basic aspect of the language or he will agree with you
and you will know he is incompetent and you have wasted a semester.


OK, yes, my book says they have "strong relationship". I guess I should
study harder...
Well actually if I don't free() the memory I allocated, will the memory
be free after the program quits?

And you believe this is an excuse to write sloppy code?


So is it required to free() the memory I allocated. I didn't do that
before unless required.

Nov 14 '05 #11
On Sat, 01 May 2004 15:29:50 -0500, fix <fi*@here.com> wrote:

Barry Schwarz wrote:
>And this is the code I make a new trie node, initialize and return it.
>TrieNode *newTrieNode()
>{
> int i;
> // Allocate memory for the node
> TrieNode *node = (TrieNode *)malloc(sizeof(TrieNode));
Don't cast the return from malloc. It doesn't help and can prevent
the compiler from warning you that you forgot to include stdlib.h.
Such an omission would lead to undefined behavior.

I did read post about this problem. I would like to omit it if possible.
Well I am using VS.NET to write the programs, test and compile, if I
cast it, there's a warning, if I don't, there isn't.

Go back and read my original comment. Did you include stdlib.h?


OK, I didn't. But why does my program can still use malloca?


What is malloca?

Your program uses malloc because you coded it to. Under C89, if you
call a function without a prototype, the compiler assumes that the
arguments are the correct type and the function returns an int. It
then generates the appropriate clues for the linker to include that
function in you program. Since the assumed return type is incorrect
for malloc, you have invoked undefined behavior.
But the problem is, these programs are assignment of my computer science
class, and the prof said that I have to make sure it works on gcc. gcc
does give me error if I don't cast:
warning: initialization makes pointer from integer without a cast
if I cast, it doesn't give me this.

This is exactly the warning you need to avoid undefined behavior. The
warning tells you the compiler thinks malloc is returning an integer.
Since you know malloc returns a pointer to void, the question is why
does the compiler think this? The answer is because you never told
the compiler what malloc really did. The reason you never told it is
because you forgot to include stdlib.h which contains the prototype
for malloc.

I don't know anything about gcc or your hardware but consider the case
where returned pointers and returned integers use different hardware
registers. The cast shuts up the warning without solving the problem.
All the cast does is tell the compiler to generate code that takes the
supposed integer return from malloc and convert it without warning to
a pointer. Since malloc doesn't return an integer, this still makes
no sense.

I did turn in my first C program without any cast, I got marks deduced.

If you turned in a program with warnings, what do you expect.

> // **********
> *(node->children) = (TrieNode *)malloc(sizeof(TrieNode *) * 27);
This is a problem. Work through the types.

node is a pointer to struct.
node->children is an array of 27 pointers to struct.
*(node->children) is exactly equivalent to (node->children)[0]
which is the first element of that array. This element is obviously a
pointer to struct.
The space you allocate is not sufficient to hold such a struct.
The struct consists of 27 struct pointers plus a void pointer plus any
padding. You allocate only enough space for the 27 struct pointers.
At this point you have committed the unpardonable sin of lying to
the compiler. You have told it that node->children[0] will point to
a struct and it doesn't.

On top of all that, you don't need this code. The struct already
contains an array of 27 pointers so you don't need another set.

Hm...... I am not that clear about what I learnt. A var[] and *var can
be used interchangeably, but what's the difference? Does the compiler
allocate space for var[] but not *var?

NO NO NO NO. A var[] is an array. A *var is a pointer. While they
share a certain amount of common syntax using subscript notation they
are by no means interchangeable. Read the faq. Look in your text.
Google through the archives for postings that talk about pointers and
arrays, especially those by CBFalconer.

And for heaven's sake, don't say this to your instructor. The only
possible result is bad. Either he will downgrade you for not
understanding a basic aspect of the language or he will agree with you
and you will know he is incompetent and you have wasted a semester.


OK, yes, my book says they have "strong relationship". I guess I should
study harder...
Well actually if I don't free() the memory I allocated, will the memory
be free after the program quits?

And you believe this is an excuse to write sloppy code?


So is it required to free() the memory I allocated. I didn't do that
before unless required.


The standard does not specify what the operating system will do when
you program terminates. It is never wrong to clean up after your self
and on a "not well designed system" it may in fact be necessary. I
don't have a clue about whether your system will clean up your mess or
not but in this newsgroup we don't depend on system specific behavior.
<<Remove the del for email>>
Nov 14 '05 #12
On Sat, 01 May 2004 17:52:06 GMT, CBFalconer <cb********@yahoo.com>
wrote:
Barry Schwarz wrote:
On Sat, 01 May 2004 01:19:14 -0500, fix <fi*@here.com> wrote:

... snip ...

Hm...... I am not that clear about what I learnt. A var[] and
*var can be used interchangeably, but what's the difference?
Does the compiler allocate space for var[] but not *var?


NO NO NO NO. A var[] is an array. A *var is a pointer. While
they share a certain amount of common syntax using subscript
notation they are by no means interchangeable. Read the faq.
Look in your text. Google through the archives for postings that
talk about pointers and arrays, especially those by CBFalconer.


I think you mean Chris Torek :-) Look for 'the rule'.


Sorry about that but at least I did get four of the letters right,
though not always in the correct order.
<<Remove the del for email>>
Nov 14 '05 #13
fix


Barry Schwarz wrote:
OK, I didn't. But why does my program can still use malloca?

What is malloca?


It's a typo.
Your program uses malloc because you coded it to. Under C89, if you
call a function without a prototype, the compiler assumes that the
arguments are the correct type and the function returns an int. It
then generates the appropriate clues for the linker to include that
function in you program. Since the assumed return type is incorrect
for malloc, you have invoked undefined behavior.


I meant, I don't include the header and can still call malloc, does the
compiler know where to find the actual malloc implementation?
But the problem is, these programs are assignment of my computer science
class, and the prof said that I have to make sure it works on gcc. gcc
does give me error if I don't cast:
warning: initialization makes pointer from integer without a cast
if I cast, it doesn't give me this.
This is exactly the warning you need to avoid undefined behavior. The
warning tells you the compiler thinks malloc is returning an integer.
Since you know malloc returns a pointer to void, the question is why
does the compiler think this? The answer is because you never told
the compiler what malloc really did. The reason you never told it is
because you forgot to include stdlib.h which contains the prototype
for malloc.

I don't know anything about gcc or your hardware but consider the case
where returned pointers and returned integers use different hardware
registers. The cast shuts up the warning without solving the problem.
All the cast does is tell the compiler to generate code that takes the
supposed integer return from malloc and convert it without warning to
a pointer. Since malloc doesn't return an integer, this still makes
no sense.

I did turn in my first C program without any cast, I got marks deduced.
If you turned in a program with warnings, what do you expect.

>> // **********
>> *(node->children) = (TrieNode *)malloc(sizeof(TrieNode *) * 27);
>
>
>This is a problem. Work through the types.
>
> node is a pointer to struct.
> node->children is an array of 27 pointers to struct.
> *(node->children) is exactly equivalent to (node->children)[0]
>which is the first element of that array. This element is obviously a
>pointer to struct.
> The space you allocate is not sufficient to hold such a struct.
>The struct consists of 27 struct pointers plus a void pointer plus any
>padding. You allocate only enough space for the 27 struct pointers.
> At this point you have committed the unpardonable sin of lying to
>the compiler. You have told it that node->children[0] will point to
>a struct and it doesn't.
>
>On top of all that, you don't need this code. The struct already
>contains an array of 27 pointers so you don't need another set.

Hm...... I am not that clear about what I learnt. A var[] and *var can
be used interchangeably, but what's the difference? Does the compiler
allocate space for var[] but not *var?
NO NO NO NO. A var[] is an array. A *var is a pointer. While they
share a certain amount of common syntax using subscript notation they
are by no means interchangeable. Read the faq. Look in your text.
Google through the archives for postings that talk about pointers and
arrays, especially those by CBFalconer.

And for heaven's sake, don't say this to your instructor. The only
possible result is bad. Either he will downgrade you for not
understanding a basic aspect of the language or he will agree with you
and you will know he is incompetent and you have wasted a semester.


OK, yes, my book says they have "strong relationship". I guess I should
study harder...

Well actually if I don't free() the memory I allocated, will the memory
be free after the program quits?
And you believe this is an excuse to write sloppy code?


So is it required to free() the memory I allocated. I didn't do that
before unless required.

The standard does not specify what the operating system will do when
you program terminates. It is never wrong to clean up after your self
and on a "not well designed system" it may in fact be necessary. I
don't have a clue about whether your system will clean up your mess or
not but in this newsgroup we don't depend on system specific behavior.


Wouldn't that be too hard to find out what is allocated and what is not?
That'll be a pain if that is a huge program. Is there any way to get a
list of memory allocated by the program and free them all when the
program quits?

Nov 14 '05 #14
On Sat, 01 May 2004 21:36:06 -0500, fix <fi*@here.com> wrote:


Barry Schwarz wrote:
OK, I didn't. But why does my program can still use malloca?

What is malloca?


It's a typo.
Your program uses malloc because you coded it to. Under C89, if you
call a function without a prototype, the compiler assumes that the
arguments are the correct type and the function returns an int. It
then generates the appropriate clues for the linker to include that
function in you program. Since the assumed return type is incorrect
for malloc, you have invoked undefined behavior.


I meant, I don't include the header and can still call malloc, does the
compiler know where to find the actual malloc implementation?


Go back and read the paragraph again. The compiler doesn't find the
actual code for malloc. The linker does.

And no, you cannot still call it. Any attempt to do so invokes
undefined behavior, regardless of whether or not the compiler
generates a diagnostic.

Do you have your warning level set to max? Many compilers will
generate a warning that there is no prototype in scope.

snip
The standard does not specify what the operating system will do when
you program terminates. It is never wrong to clean up after your self
and on a "not well designed system" it may in fact be necessary. I
don't have a clue about whether your system will clean up your mess or
not but in this newsgroup we don't depend on system specific behavior.


Wouldn't that be too hard to find out what is allocated and what is not?
That'll be a pain if that is a huge program. Is there any way to get a
list of memory allocated by the program and free them all when the
program quits?


It's only too hard if you code your program before you design it. A
well designed program will have one fclose for every successful fopen
and one free for every successful malloc, whether explicit or implied.
This is one of the reasons there is more to programming than merely
learning the language. (Just as an aside, it is legal to free the
NULL pointer returned by an unsuccessful malloc but it is not legal to
fclose the NULL pointer returned by an unsuccessful fopen.)

There is no standard language feature that will tell you all the areas
you have allocated. You have to keep track of them as you allocate
them. Since you normally assign the returned address to a pointer,
this is not as onerous as it sounds.
<<Remove the del for email>>
Nov 14 '05 #15
fix wrote:
Barry Schwarz wrote:
OK, I didn't. But why does my program can still use malloca?


What is malloca?


It's a typo.


No, it's a non-standard extension used by some systems to allocate
memory on the stack (on systems with a stack). This has the
advantage/flaw that the memory is automatically deallocated when
the function is exited and that allocation can be very quick.

--
A: Because it fouls the order in which people normally read text.
Q: Why is top-posting such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
Nov 14 '05 #16
CBFalconer wrote:
fix wrote:
Barry Schwarz wrote:
What is malloca?


It's a typo.


No, it's a non-standard extension used by some systems to allocate
memory on the stack (on systems with a stack).


That would normally be spelt `alloca', so it'd still be a typo.

--
++acr@,ka"
Nov 14 '05 #17
fix
Sam Dennis wrote:
CBFalconer wrote:
fix wrote:
Barry Schwarz wrote:

What is malloca?

It's a typo.


No, it's a non-standard extension used by some systems to allocate
memory on the stack (on systems with a stack).

That would normally be spelt `alloca', so it'd still be a typo.


Yup, it is just a typo, I didn't know about those extensions.

Nov 14 '05 #18
fix

Barry Schwarz wrote:
On Sat, 01 May 2004 21:36:06 -0500, fix <fi*@here.com> wrote:


Barry Schwarz wrote:

OK, I didn't. But why does my program can still use malloca?
What is malloca?
It's a typo.

Your program uses malloc because you coded it to. Under C89, if you
call a function without a prototype, the compiler assumes that the
arguments are the correct type and the function returns an int. It
then generates the appropriate clues for the linker to include that
function in you program. Since the assumed return type is incorrect
for malloc, you have invoked undefined behavior.


I meant, I don't include the header and can still call malloc, does the
compiler know where to find the actual malloc implementation?

Go back and read the paragraph again. The compiler doesn't find the
actual code for malloc. The linker does.


OK, I got it, I was just treating the thing after I wrote my program as
"compiling" and the program does that as the "compiler".
And no, you cannot still call it. Any attempt to do so invokes
undefined behavior, regardless of whether or not the compiler
generates a diagnostic.

Do you have your warning level set to max? Many compilers will
generate a warning that there is no prototype in scope.
Hm...... I have written several programs without including stdlib.h, but
I can still do malloc. I am using two compiler, one gives me the warning
but the other does not.
snip
The standard does not specify what the operating system will do when
you program terminates. It is never wrong to clean up after your self
and on a "not well designed system" it may in fact be necessary. I
don't have a clue about whether your system will clean up your mess or
not but in this newsgroup we don't depend on system specific behavior.


Wouldn't that be too hard to find out what is allocated and what is not?
That'll be a pain if that is a huge program. Is there any way to get a
list of memory allocated by the program and free them all when the
program quits?

It's only too hard if you code your program before you design it. A
well designed program will have one fclose for every successful fopen
and one free for every successful malloc, whether explicit or implied.
This is one of the reasons there is more to programming than merely
learning the language. (Just as an aside, it is legal to free the
NULL pointer returned by an unsuccessful malloc but it is not legal to
fclose the NULL pointer returned by an unsuccessful fopen.)

There is no standard language feature that will tell you all the areas
you have allocated. You have to keep track of them as you allocate
them. Since you normally assign the returned address to a pointer,
this is not as onerous as it sounds.


I guess there is still a long time for me to learn writing "good" C
programs. I came from lanugages that does not have pointer, and thus no
deallocating memory. I have done a program which require me to free all
the memory which I have allocated, but the pain comes from the nature of
the program - it is using nested structure, and what I have to do is to
go deep into the structure and kill the children because their parents.

Nov 14 '05 #19
On Sun, 02 May 2004 14:29:07 -0500, fix <fi*@here.com> wrote:

Barry Schwarz wrote:
On Sat, 01 May 2004 21:36:06 -0500, fix <fi*@here.com> wrote: snip
I meant, I don't include the header and can still call malloc, does the
compiler know where to find the actual malloc implementation?

Go back and read the paragraph again. The compiler doesn't find the
actual code for malloc. The linker does.


OK, I got it, I was just treating the thing after I wrote my program as
"compiling" and the program does that as the "compiler".
And no, you cannot still call it. Any attempt to do so invokes
undefined behavior, regardless of whether or not the compiler
generates a diagnostic.

Do you have your warning level set to max? Many compilers will
generate a warning that there is no prototype in scope.


Hm...... I have written several programs without including stdlib.h, but
I can still do malloc. I am using two compiler, one gives me the warning
but the other does not.


The presence or absence of a warning is merely a quality of
implementation issue for the compiler.

The fact that you invoke undefined behavior but your program APPEARS
to work is just really rotten luck. It has caused you to learn some
things which are in fact not correct and allowed you to develop some
bad habits that will become more difficult to correct the later you
try.

If you want to keep on coding undefined behavior, that is your
privilege. Many consider repeated posting of such code the mark of a
troll and see no point in responding to someone not interested in
learning.

snip

<<Remove the del for email>>
Nov 14 '05 #20
fix


Barry Schwarz wrote:
On Sun, 02 May 2004 14:29:07 -0500, fix <fi*@here.com> wrote:

Barry Schwarz wrote:

On Sat, 01 May 2004 21:36:06 -0500, fix <fi*@here.com> wrote:
snip
I meant, I don't include the header and can still call malloc, does the
compiler know where to find the actual malloc implementation?
Go back and read the paragraph again. The compiler doesn't find the
actual code for malloc. The linker does.


OK, I got it, I was just treating the thing after I wrote my program as
"compiling" and the program does that as the "compiler".

And no, you cannot still call it. Any attempt to do so invokes
undefined behavior, regardless of whether or not the compiler
generates a diagnostic.

Do you have your warning level set to max? Many compilers will
generate a warning that there is no prototype in scope.


Hm...... I have written several programs without including stdlib.h, but
I can still do malloc. I am using two compiler, one gives me the warning
but the other does not.

The presence or absence of a warning is merely a quality of
implementation issue for the compiler.

The fact that you invoke undefined behavior but your program APPEARS
to work is just really rotten luck. It has caused you to learn some
things which are in fact not correct and allowed you to develop some
bad habits that will become more difficult to correct the later you
try.

If you want to keep on coding undefined behavior, that is your
privilege. Many consider repeated posting of such code the mark of a
troll and see no point in responding to someone not interested in
learning.

snip


But well, I learnt from this. I included the header, I don't cast my
pointers returned by malloc anymore...... Was just wondering why it works.

Nov 14 '05 #21

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

8 posts views Thread by Steve Lambert | last post: by
7 posts views Thread by Frank M. | last post: by
10 posts views Thread by Adam Warner | last post: by
204 posts views Thread by Alexei A. Frounze | last post: by
5 posts views Thread by Stijn van Dongen | last post: by
2 posts views Thread by Simon Morgan | last post: by
7 posts views Thread by Kathy Tran | last post: by
15 posts views Thread by Paminu | last post: by
20 posts views Thread by Cyn | last post: by
reply views Thread by zhoujie | last post: by
1 post views Thread by Mortomer39 | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.