On Tue, 27 Jul 2021 15:13:57 +0100
> On 27/07/2021 07:24, Rod Pemberton wrote:
> > On Sat, 24 Jul 2021 13:40:54 +0100
> > James Harris <james.h...@gmail.com
> >> In either case the point is that the code tests for a pointer being
> >> null because null means that there is no node.
> >> As with the theme of this topic, there is a particular address
> >> which is guaranteed not to refer to an object.
> > Well, I see this is a special case - abuse of NULL actually - which
> > was outside the topic of the prior conversation, which was avoiding
> > NULL pointer dereferences, in general, for a language.
> > Anyway, a NULL address is not required to be used here as a node
> > terminator. E.g., other magic numbers such as -1 (all bits set) or
> > (zero if not equivalent to NULL) could be used as well. The choice
> > of using NULL as a sentinel (or magic value or canary etc) is
> > completely arbitrary here. I.e., the node terminator in the tree
> > only needs to not point to any valid node in the tree. For
> > example, you could create your own "NULL node", which points to an
> > empty node, not inserted into the tree.
> You could do that, but what would you call it?
Whatever you want. Something appropriate would probably be good. Not
that it really matters, as whatever you name it, it won't help a
non-native language speaker understand it, just like names of
everything else in a program. Have you ever tried reading a program
coded in a language you don't know? ...
> Would you need to create a custom 'null'-pointer value for every
> pointer type?
No, since you don't need to detect NULL for every pointer type. In
general, you only need to detect NULL when a pointer hasn't been
properly initialized or has been changed to NULL. If the pointer is
properly initialized and nothing resets/sets it to NULL, why would you
need to check for NULL? ... This is similar to keeping track of stack
objects in Forth, or free flags for 6502, or buffer size in C, etc. Is
the programmer keeping track or not? If not, then NULL check overload.
> So fopen() would return NULL_NOFILE for failed operation, and
> so on for every such function in existence.
How is that any different from returning NULL for every failed
operation? I.e., you clearly have an arbitrary preference. Does it
matter if the failure sentinel is NULL, 0, -1, 0xDEAD, 0xBEEF, etc?
The programmer has to use whatever the language provides. So, why
should the failure sentinel be NULL if that could cause problems?
> >>> As the programmer, you should be coding your program to not have
> >>> pointers set to NULL especially if the pointer is to be
> >>> dereferenced. I.e., initialize the pointer prior to use.
> >> Null doesn't mean uninitialised.
> > True.
> >> A pointer can be initialised to
> >> null, as it would be for the tree-walking code, above.
> > IMO, that (initializing a pointer to NULL) is really bad idea.
> Do you have the same opinion about 0 (zero) being used to inialise
> signed and unsigned ints of any width, various widths of floats, big
> integers, and any of a myriad of derived numeric types?
No, because non-pointers aren't supposed to be dereferenced.
No, because integers on certain processors and floats on certain
math coprocessors require all bits zero for the hardware to recognize
them as zero.
> > Doing this may be acceptable for the binary tree or a graph, if you
> > place the appropriate checks. However, in general, it's a bad idea
> > to set a pointer to NULL, especially in C, as this is what leads to
> > the unintentional dereferencing of NULL pointers, which is what you
> > said you wanted to avoid.
> So instead you get unintentional [dereferencing] of pointers
> to dummy objects that are not meant to be accessed,
No. These are valid objects or should be.
> which is now undetectable.
... only because you're assumption is incorrect?
> At least NULL derefs are normally detected, /when a program goes
When NULL derefs are detected, this halts and/or crashes the program.
How is that any better than coding the program to not fail, and not use
> How would you even get a language to insert checks for invalid
> pointer accesses, when the knowledge of what is invalid depends on
> user code within the application, outside of the language? Languages
> KNOW about Null.
What invalid pointer accesses? ... Once you initialize your pointers
to point to valid objects, there is no such thing.
If a "Null node" is used instead of NULL, the dereference will be to
known data instead of bad data, which should be designed to work with
the program without failure, and without producing an incorrect result.
> > No. Unfortunately, none of the examples do.
> You accept that some sentinel value is needed.
... is needed for terminal nodes in a linked-list or tree.
> You do not accept that that should be NULL
> and consider it an error.
> Most people disagree.
This is going to sound really arrogant, but I assure you that it's not.
People have always disagreed with me. That has never made them correct.
> > The fact that bad coding practice has been accepted and perhaps is
> > widely used, doesn't make it good practice. Does it?
> > Interestingly, I think I've only coded a binary tree once since
> > Pascal in High School over 3 some decades ago ... It's a really
> > useless data structure, much like a linked-list.
> You don't use trees at all?
It seems that I have /one/ piece of code which uses a linked-list,
and it used NULL as the terminator, but it's old, and I never used it.
> I guess you've never implemented a language
> then, because the syntax of most languages is tree-shaped.
They're tree-shaped, but only if you allow them to be represented that
way. You don't have to. Why should you? Natural fit? If you can
represent them in a manner which better fits the program or language,
why wouldn't you do that instead of using the natural fit?
> > Computer Science professors always
> > force the students to solve every problem using a linked-list.
> What would you use instead for a data structure [...?]
> What would you use instead for a data structure that can
> incrementally grow and only needs to be serially accessed?
Both of my answers can "incrementally grow", both can be "serially
accessed" too. You can store all the information in a tree or
linked-list as a link-less, node-less stack or array. However, using
just one pointer into the stack/array will allow you to do everything
you need to access, manipulate, delete, etc. The only real issue is
insertion. So, don't insert or use other techniques to locate the data
elsewhere. This technique has less memory overhead too, since the
header structure for the linked-list or nodes containing all the
pointers isn't present.
> In a lower level language, a linked list is the perfect solution!
> (A few years ago, I converted a compiler written in a dynamic
> language, with resizable lists that could be organised into trees
> without using explicit pointers, into a lower level language.
> Most of those reduced down to tight, efficient, linked lists. Trees
> (symbol tables and ASTs) were linked multiple ways via pointers, to
> result in a version that ran about 30 times faster. Null/nil values
> were used everywhere.)
They probably could've been reduced down to tight, efficient, arrays or
In general, I see linked-lists as over-prescribed, overused, usually
unnecessary, having excess overhead, and used as a crutch by
inexperienced programmers to eliminate needing to think about using a
different solution. They've become a one-size fits all technique.