Richard said:
Richard said:
(e-mail address removed) wrote:
Al Bowers wrote:
[...] It seems that the OP wants a pointer to the tail of the
list for some reason unknown.
Unknown?!?! Look closely. It causes the algorithm to stop
attempting to add nodes. It is essentially a simple feedback
that lets you know that you are out of memory (or more
generally that an add_item has failed).
Which is a wrong way to handle such situations. If add_item()
fails, it should return a failure status, not fiddle with a
pointer.
Explain how this is wrong.
If you can't see without my help why scribbling over a tail pointer,
which is potentially useful elsewhere, is inferior to returning a
proper error status from a function which now returns nothing at
all, I'm afraid I can explain all I want, but you're never going to
get it.
The "reference to tail link" is overwritten when you are out of memory.
True it would be nice to have all sorts of O(1) assistance to deal
with whatever you are going to do about an out-of-memory situation, but
a scenario where this truly matters escapes my imagination at the
moment.
Your approach complexifies the main case in order to make dealing with
marginal cases faster. Trust me, the understanding problem is not
mine.
Which is completely irrelevant to what the OP himself wanted.
The code I wrote is plug-in compatible with what the OP wrote (without
changing his intended semantics.)
[...] _You_
scribble over the tail pointer; this is a bad thing, because the OP
presumably wants to use it for something.
He wants to use it to add_item(). I only "scribble over" the reference
to the tail link when an extremely marginal situation has occurred
which needs drastic attention and special case code to deal with. And
unlike the other suggestions posted, mine doesn't tie down the
implementation by *forcing* it to have a tail pointer.
There isn't a real sense in which the tail pointer is not available.
Think about it, suppose we were both to implement the failed malloc
scenario in our respective solutions:
1. If we decide that the list just must be destroyed and all further
processing to stop, then knowing the tail doesn't help.
2. If we decide that the upper level code should just stop adding items
and leave the list as is, and furthermore that add_item()/pop_iten()
are the only list manipulation functions, then again knowing the tail
doesn't help. My solution intrinsically stops add_item() from further
action no matter what, so you can defer the error check until the end
after your loop (and thus collect your error checking all in one
place). With your solution you must deal with the error from *INSIDE*
the inner loop.
3. If we have a way of coercing malloc to start functioning once more
(maybe we'll free memory from somewhere else or something like that)
then indeed your solution has a slight advantage. For my solution you
could copy the reference to tail link to an extra variable just before
calling add_item(), then recover it from inside the if(NULL == ...)
error case. But if you don't want to pay mainline inner loop
penalties, you can alternatively, just regenerate the reference to tail
link from scratch inside the error case (the reasoning being that this
case is so marginal that the high cost just doesn't matter.)
So I don't see that your complaint about my preference (I'm sure I'm
not the first person to have thought of this) as being seriously
legitimate. Your preference assumes the existence of a completely
artifical "tail entry" which aliases NULL with "there is no nail entry"
and requires you to handle two cases. In my solution there is *ALWAYS*
a reference to tail link -- there is no distinction between empty, one
entry or any other cases of linked lists.
Now if we add deletion into the mix, which of our solutions do you
think will be easier to test, design and implement?