By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
443,973 Members | 1,901 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 443,973 IT Pros & Developers. It's quick & easy.

((node*)&head)->next

P: n/a
Given that next is the first field in struct node,
and head is a pointer to node,
does assigning ((node*)&head)->next safely assign head ?

Illustration (this code works on many platforms)
#include <stdlib.h>
#include <stdio.h>

/* node structure for linked list */
typedef struct node
{
struct node* next;
char payload;
} node;

int main(void)
{
node *head, *last, *temp;
int c;
/* build list from stdin */
last = (node*)&head;
while ((c = getchar())!=EOF)
{
if ((temp = malloc(sizeof(node)))==NULL)
return 1;
temp->payload = c;
last->next = temp;
last = temp;
}
last->next = NULL;
/* then output list */
temp = head;
while (temp!=NULL)
{
putchar(temp->payload);
temp = temp->next;
}
return 0;
}

--
François Grieu
Nov 14 '05 #1
Share this Question
Share on Google+
3 Replies


P: n/a
In article <fg**************************@individual.net>
Francois Grieu <fg****@francenet.fr> wrote:
Given that next is the first field in struct node,
and head is a pointer to node,
does assigning ((node*)&head)->next safely assign head ?

Illustration (this code works on many platforms)
I would be surprised to find a platform on which this does *not*
work:
#include <stdlib.h>
#include <stdio.h>

/* node structure for linked list */
typedef struct node
{
struct node* next;
char payload;
} node;

int main(void)
{
node *head, *last, *temp;
int c;
/* build list from stdin */
last = (node*)&head;
while ((c = getchar())!=EOF)
{
if ((temp = malloc(sizeof(node)))==NULL)
return 1;
temp->payload = c;
last->next = temp;
last = temp;
}
last->next = NULL;

[etc]

But there is no need to resort to such subterfuge. Simply use
pointers the way they are intended:

node *head, *temp;
node **npp = &head;

while ((c = getchar()) != EOF) {
temp = malloc(sizeof *temp);
if (temp == NULL)
return EXIT_FAILURE;
temp->payload = c;
*npp = temp;
npp = &temp->next;
}
*npp = NULL;

While the head is just a pointer (of type "struct node *", aka
"node *"), each node also contains a pointer of that same type.
If we point a separate pointer ("npp") at each pointer in turn, we
can set each pointed-to pointer with absolute 100% guaranteed
safety, even though the "head" pointer is *just* a pointer, and
the other pointers are elements of a larger collection.

Naturally, to point to "struct node *" objects, we need a pointer
of type "struct node **" (aka "node **").

Note that this code continues to work even if the "next" field is
moved elsewhere in the list structure -- while the original code,
with its cast, stops working.
--
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (40°39.22'N, 111°50.29'W) +1 801 277 2603
email: forget about it http://web.torek.net/torek/index.html
Reading email is like searching for food in the garbage, thanks to spammers.
Nov 14 '05 #2

P: n/a
On Mon, 13 Dec 2004 08:53:27 +0100, Francois Grieu wrote:
Given that next is the first field in struct node,
and head is a pointer to node,
does assigning ((node*)&head)->next safely assign head ?
This isn't safe because the alignment of a node structure may be stricter
than the alignment of a pointer to node. Also you are creating a pointer
to node value which isn't null and doesn't point at a valid node object,
or 1 past the end of an array of nodes.
Illustration (this code works on many platforms)


Yes, it is likely to work on many platforms but as far as C is concerned
it invokes undefined behaviour.

Chris's solution is well defined hence better.

Lawrence

Nov 14 '05 #3

P: n/a
Chris Torek <no****@torek.net> wrote:
Simply use pointers the way they are intended

node *head, *temp;
node **npp = &head;

while ((c = getchar()) != EOF) {
temp = malloc(sizeof *temp);
if (temp == NULL)
return EXIT_FAILURE;
temp->payload = c;
*npp = temp;
npp = &temp->next;
}
*npp = NULL;


Yes, that's clean.

For reasons not apparent in the sample code that I posted,
I wanted to keep a pointer to the last node in the list,
and Chris's code does not do that. But now I realize
that a pointer to the "next" field in the last node in the
list will do just as well, if not better.

Thanks Chris. Also, thanks Lawrence for a concrete reason
why the original code could fail (beside plain non-conformance).

--
François Grieu
Nov 14 '05 #4

This discussion thread is closed

Replies have been disabled for this discussion.