Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C Programming > pointers to struct members

Reply
Thread Tools

pointers to struct members

 
 
Emanuele Blanco
Guest
Posts: n/a
 
      04-17-2004
Hi there,

I just compiled a program that uses linked lists (needed it as an homework
for my Programming course at University). It works flawlessly, even if I
notice a thing. Here's my linked list declaration:

struct node {
float item;
struct node *next;
};

typedef struct node *list;

I need a function that removes a node in that list, without checking the
emptyness of the list. So here's my code:

void remove_key(list *lista, float key) {
list temp=*lista;
if (temp->item == key) {
*lista=temp->next;
free(temp);
}
else
remove_key((list *)(temp->next), key);
}

My question is: I needed the casting to list * to make the recursive call
work. I wasn't able to get it work using a syntax like
remove_key(*(temp->next), key). There's a proper syntax to point to a struct
member, or do I need the cast ? Compiling with gcc makes the incompatible
parameter type error.

Thanks in advance and sorry for my English.

--
Emanuele Blanco
PGP Key Available


 
Reply With Quote
 
 
 
 
Barry Schwarz
Guest
Posts: n/a
 
      04-17-2004
On Sat, 17 Apr 2004 14:33:34 +0200, "Emanuele Blanco"
<> wrote:

>Hi there,
>
>I just compiled a program that uses linked lists (needed it as an homework
>for my Programming course at University). It works flawlessly, even if I
>notice a thing. Here's my linked list declaration:
>
>struct node {
> float item;
> struct node *next;
>};
>
>typedef struct node *list;
>
>I need a function that removes a node in that list, without checking the
>emptyness of the list. So here's my code:
>
>void remove_key(list *lista, float key) {
> list temp=*lista;
> if (temp->item == key) {
> *lista=temp->next;
> free(temp);
> }
> else
> remove_key((list *)(temp->next), key);
>}
>
>My question is: I needed the casting to list * to make the recursive call
>work. I wasn't able to get it work using a syntax like
>remove_key(*(temp->next), key). There's a proper syntax to point to a struct
>member, or do I need the cast ? Compiling with gcc makes the incompatible
>parameter type error.


The compiler diagnostic is not the problem. It is a description of
the problem. While the cast silences the compiler, it does nothing
about the problem itself.

remove_key requires a pointer to pointer to struct as its first
argument. That means when you dereference your argument, the value
you end up with is a pointer to struct. Phrased another way, the
value in lista is an address. If you examine the appropriate number
of bytes at that address, you will find another address. It is this
second address which identifies the location of the struct.

What did your code do? You took the value of temp->next which is a
pointer to struct, that is the address of a struct. You told the
compiler: don't change the value but convert it to the form of pointer
to pointer to struct. (On most machines, the form of a pointer to
struct and pointer to pointer to struct are the same. However, the
compiler recognizes a difference between struct* and struct** so the
cast makes the compiler happy and also performs whatever magic is
necessary in case the two forms are not the same.) You then pass this
value to the next incarnation (or whatever the correct term is for the
target of the recursive call) of remove_key. remove_key knows that
the (new) value of lista points to address. Unfortunately it doesn't.
The new value of lista points to exactly what the old value of
temp->next pointed to. Namely, another instance of the struct. It
turns out that the bytes at the beginning of the struct, which
remove_key is trying to interpret as an address, are actually part of
the float that is the first item in the struct. Welcome to undefined
behavior.

The moral of the story is you cannot lie to your compiler. When you
use a cast, what you are really saying to the compiler is that even if
this expression doesn't look like this new type, it really is.
Therefore, don't change the value but do "reformat" it so it "looks
like" the type specified. If this is not the situation in your code,
then the cast is the wrong solution.

remove_key requires a value (C always passes by value) that points to
a pointer. The proper method of constructing such a value when all
you have is the original pointer is the "address of" operator, the &.
What your code needs is
remove_key(&(temp->next), key);
Since -> has higher precedence than &, the internal parentheses are
superfluous but some like to keep them for the visual hint.

The next question is: why are you doing this recursively? It is
relatively simple (and much easier to debug) to do this with a loop.


<<Remove the del for email>>
 
Reply With Quote
 
 
 
 
Emanuele Blanco
Guest
Posts: n/a
 
      04-17-2004
"Barry Schwarz" <> ha scritto nel messaggio
news:c5rr1i$oql$0@216.39.135.209...

[CUT]

> remove_key requires a value (C always passes by value) that points to
> a pointer. The proper method of constructing such a value when all
> you have is the original pointer is the "address of" operator, the &.
> What your code needs is
> remove_key(&(temp->next), key);
> Since -> has higher precedence than &, the internal parentheses are
> superfluous but some like to keep them for the visual hint.


Thanks for explanations. I'm new into managing dynamic data structures (like
linked lists) and programming it in C, as I'm studying Computer Sciences.
Now I understand it. I was not sure about the casting, but it worked and
that was good. But not good enough to live without asking I used to
manage passing pointers with & operator, but haven't thought about it in
this case. It's really kind of you. Thanks a lot.

> The next question is: why are you doing this recursively? It is
> relatively simple (and much easier to debug) to do this with a loop.


I'm also learning programming using recursion ... and a code like this is
also simple in the recursive way.

--
Emanuele Blanco
PGP Key Available


 
Reply With Quote
 
Christopher Benson-Manica
Guest
Posts: n/a
 
      04-19-2004
Emanuele Blanco <> spoke thus:

> I'm also learning programming using recursion ... and a code like this is
> also simple in the recursive way.


If this is your first attempt at recursion, you might start with
something simpler, say the canonical factorial program.

--
Christopher Benson-Manica | I *should* know what I'm talking about - if I
ataru(at)cyberspace.org | don't, I need to know. Flames welcome.
 
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
pointers, pointers, pointers... cerr C Programming 12 04-07-2011 11:17 PM
Difference between static final members and final static members(if any)? JFCM Java 4 02-07-2006 11:32 AM
struct my_struct *p = (struct my_struct *)malloc(sizeof(struct my_struct)); Chris Fogelklou C Programming 36 04-20-2004 08:27 AM
Can nested class members access private members of nesting class? CoolPint C++ 8 12-14-2003 02:30 PM



Advertisments
 



1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57