In article <ea*********@news1.newsguy.comI wrote, in part:
> struct list *l1, *l2;
struct list **l1end = &l1, **l2end = &l2;
struct list *p;
for (p = orig_list; p != NULL; p = p->next) {
if (goes_in_l1(p)) {
*l1end = p;
l1end = &p->next;
} else {
*l2end = p;
l2end = &p->next;
}
}
*l2end = NULL;
*l1end = l2;
/* new list is now headed by l1 */
The order of the last two lines is important. (Exercise: why?)
In article <11**********************@b28g2000cwb.googlegroups .com>,
Bill Pursell <bi**********@gmail.comwrote:
>assert(l1end->next == l2end);
This should not even compile (unless you turn on NDEBUG), since
l1end->next has type "struct list *", while "l2end" has type
"struct list **".
><OT I would call then temporary pointers l1head and l2head.
In other words, you can add things to the start of a list, but not
the end.
But that is not what they are; and this code *does* add things to
the end of each list. That is the tricky thing about l1end and
l2end: each time, it points to the "struct list *" that should
point to a new item in the corresponding list. Initially, the
"struct list *" that should point to the new items are "l1" and
"l2" respectively, but as items are added to those lists, they
change.
That is, initially, we have (l1end == &l1), but once there is
one item in list l1, we have (l1end == &l1->next). When there
are two items in list l1, we have (l1end == &l1->next->next),
and so on.
It is possible to avoid the need to set *l2end to NULL before
setting *l1end to l2, by initializing l2 to NULL at the top of the
code. The assignment to *l2end is then always redundant (in the
code shown above, it is redundant if and only if at least one item
has been placed into list l2).
--
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.