
A char pointer (char *) vs. char array question
Quote:
> Hi,
> Can someone explain me this please?
> I had the following data structure:
> Name *name_head = NULL;
> Name *name_tail = NULL;
> typedef struct Name
> {
> char *name;
> struct Name *next;
> }Name;
> I was building a simple signly linked list of the above
> structure. I used the following functions to do so:
> void insert_node(Name *p_new)
[ snip -- code for inserting node ]
Quote:
> Some other function would call insert_node with a
> new node that was built like this:
> int sample_function()
> {
> char ParentName[100];
> Name *newnode;
> /* parse_html fills up ParentName with some string */
> parent_size = parse_html(ParentName, s_in, end);
> /* null terminate the string */
> ParentName[parent_size]='\0';
> /* build new node */
> newnode = (Name *)malloc(sizeof(Name);
> 100: newnode->name = ParentName
> newnode->next = NULL;
> insert_parent(newnode);
> }
> The question is this:
> I'd have my very first entry in linked list.
> ParentName say for the first entry was "James"
> then I'd have my second entry in the linked list.
> Say ParentName for the second entry is "Anne".
> When I print my linked list, I'd see Anne printed
> twice, instead of James and then Anne.
> I couldn't understand the problem.
> I later found out that the problem was in the line
> marked 100 above. Once I changed name in my Name
> structure to be char name[10] instead of char *name,
> and built new node with
> strcpy(newnode->name, ParentName)
> things worked as expected. I did see linked list items
> printed as James and Anne, instead of seeing Anne twice.
> I've got the problem resolved, but don't know why
> this problem occured in the first place? Why using
> a char * instead of char [] is such a problem? (I did
> spend quite a long time to figure this one out!)
Look again at the line labeled 100: in your first version. You were
populating each node in the list with a pointer to the same array,
namely ParentName[]. That array can only hold one value at a time.
When you ran through the list printing names, you printed the same
name each time because you were printing from the same memory
location each time.
Actually you were lucky not to have gotten total gibberish, or worse.
ParentName[] is local to sample_function(), and is not static. When
that function begins, it allocates space for ParentName[] on the
stack. When it returns, it releases the space for possible use by
other functions. By the time you try to print from it, there is no
guarantee that some other function will not have written over that
memory with other data.
For that matter, ParentName may reside at different locations at
different times, so that different list nodes may indeed point to
different locations. But those locations may not contain anything
useful.
M{*filter*}#1: Each list node needs its own distinct piece of memory to
store the associated name. Your present code includes that space
within the list node itself. That should work (as long as the names
are always short enough to fit). Another approach would be to
allocate additional memory dynamically as needed. Then there would
be two pieces of memory allocated for each node: one for the node
structure itself and one for the string to which it points.
M{*filter*}#2: When a function has a local auto (ie non-static) variable,
*NEVER* try to reference that variable after that function has
returned. On this occasion this bug didn't bite you, but you were
just lucky.
Scott McKellar
Southwestern Bell Telephone
St. Louis, MO