((node*)&head)->next

F

Francois Grieu

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;
}
 
C

Chris Torek

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.
 
L

Lawrence Kirby

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
 
F

Francois Grieu

Chris Torek said:
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).
 

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

No members online now.

Forum statistics

Threads
473,781
Messages
2,569,616
Members
45,305
Latest member
KetoMeltsupplement

Latest Threads

Top