Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

What is the data structure of a NULL?

127 views
Skip to first unread message

T

unread,
Dec 27, 2019, 4:24:22 PM12/27/19
to
Hi All,

In C++, when you make a call to Windows Kernel32.dll
and it wants a NULL for one or more of its parameters,
what exactly is the structure of a NULL? A 32 bit
word full of zeros?

Many thanks,
-T

Ian Collins

unread,
Dec 27, 2019, 4:36:29 PM12/27/19
to
The C standard defines a null pointer as

"An integer constant expression with the value 0, or such an expression
cast to type void *, is called a null pointer constant."

--
Ian.

Alf P. Steinbach

unread,
Dec 27, 2019, 4:42:22 PM12/27/19
to
There have been systems where a nullpointer was not all bits 0.

If current PC operating systems had supported pointers with segment
selectors, that would have been the situation on PC's today. However,
reasonable OSes like Windows and Linux just set up a process with one
big single segment, where all the app's pointers are offsets in that
segment. And then a nullpointer is really all bits 0.

Nullvalues of integral type are necessarily all bits 0, because the
standard requires a binary representation of integral types. In C++20
that will be further restricted to two's complement form. In contrast,
and 0 as a floating point value is not necessarily all bits 0, although
the common IEEE 754 representation (which in particular is used on the
PC: that's where the standard originated) has that property.

- Alf

T

unread,
Dec 27, 2019, 4:55:34 PM12/27/19
to
Since Kernel32.dll uses 32 bit words as pointers, a 32 bit
word will all zero's it is. Thank you!

T

unread,
Dec 27, 2019, 4:55:44 PM12/27/19
to

Alf P. Steinbach

unread,
Dec 27, 2019, 5:10:35 PM12/27/19
to
In 64-bit Windows, and that's modern Windows, kernel32.dll uses 64-bit
pointers.

Microsoft chose to keep the "32" suffixes and prefixes to ease porting
of code from 32-bit systems.

- Alf


Öö Tiib

unread,
Dec 27, 2019, 5:15:15 PM12/27/19
to
Calm down. On windows kernel32.dll is name of kernel access library.
That name does not say what size of pointers it handles since it is
same for 32-bit and 64-bit subsystem. Kernel64.dll does not exist on
windows.

Several of people reading this group use windows rarely or not
at all so stop posting constant lies and nonsense about it.


T

unread,
Dec 27, 2019, 5:24:46 PM12/27/19
to
What size is it then? 32 or 64 or do you have to figure out
if you are running a 32 bit or 64 bit edition of Windows first?

Öö Tiib

unread,
Dec 27, 2019, 5:41:28 PM12/27/19
to
It depends what kind the app is that loads that dll
On this laptop the C:\Windows\System32\kernel32.dll is 706 KB it uses
64 bit pointers and the C:\Windows\SysWOW64\kernel32.dll is 614 KB and
uses 32 bit pointers. Notice System32 64 bit, SysWOW64 32 bit.

Bart

unread,
Dec 27, 2019, 8:46:49 PM12/27/19
to
It will be 32 bits on Win32 and 64 bits on Win64. How those 32 or 64
bits are passed also depends on the system ABI.

At what level are you coding, assembly? In a well-supported HLL and
using all the myriad headers that are provided, you don't normally need
to worry about that.

(I do because I have to use WinAPI from home-made languages and don't
use the system ABI, but most people don't.)

James Kuyper

unread,
Dec 27, 2019, 8:51:07 PM12/27/19
to
That's the definition of a "null pointer constant". The definition of a
null pointer comes on the immediately following line:

"If a null pointer constant is converted to a pointer type, the
resulting pointer, called a _null pointer_, is guaranteed to compare
unequal to a pointer to any object or function."
Note that the second occurrence of the phrase "null pointer" in that
sentence is in italics, an ISO convention indicating that this sentence
constitutes the official definition of the italicized phrase. In this
case, it's a little unclear; the first part of that sentence is not
actually the definition, it's a one of several ways to obtain a null
pointer (other ways include calling various standard library functions
that are documented as returning null pointers under certain
circumstances). It's actually the end of that sentence that defines what
null pointer is: a pointer guaranteed to compare unequal to a pointer to
any object or function.

The C standard says nothing about how null pointers are represented. A
null pointer of type T* has a size in bytes equal to sizeof(T*), a
number that is implementation-defined, not standard-defined. It is
commonplace for null pointers to have all bits 0, but that's not
guaranteed, and there have been a fair number of real-world
implementations that have used other representations. At least one
popular system I've used had a segment-offset structure for addresses,
and any pointer with an offset of 0 was defined by that implementation
to be a null pointer, regardless of what the segment portion of the
address was.

Finally, note that the OP asked about NULL. NULL is the name of a macro,
#defined in several standard headers, which is required to expand into a
null pointer constant. There's a huge variety of other ways to write a
null pointer constant, so you shouldn't confuse "NULL" with "null
pointer constant". While any null pointer constant (and therefore, in
particular, NULL) will be converted into a null pointer if used in a
context where it will be converted to a pointer type, it's also
important to understand that null pointer constants are not the same
thing as null pointers.

Keith Thompson

unread,
Dec 28, 2019, 5:14:22 AM12/28/19
to
T <T...@invalid.invalid> writes:
> In C++, when you make a call to Windows Kernel32.dll
> and it wants a NULL for one or more of its parameters,
> what exactly is the structure of a NULL? A 32 bit
> word full of zeros?

You might get better answers if you explained why you want to know.

If you're making a call from C++, you can just pass a null pointer
value such as nullptr or NULL. The compiler needs to know how
it's represented. You probably don't.

--
Keith Thompson (The_Other_Keith) Keith.S.T...@gmail.com
[Note updated email address]
Working, but not speaking, for Philips Healthcare
void Void(void) { Void(); } /* The recursive call of the void */

Bo Persson

unread,
Dec 28, 2019, 5:28:29 AM12/28/19
to
Please note that, historically, the "32" was added to indicate that it
is no longer a 16-bit Windows (like Windows 1, 2, and 3 was).

When moving from 32 to 64 bits, the names were *not* changed. :-)

So, the suffix 32 just means "not 16".


Bo Persson

Ned Latham

unread,
Dec 28, 2019, 9:33:15 AM12/28/19
to
Keith Thompson wrote:
> T writes:
> >
> > In C++, when you make a call to Windows Kernel32.dll
> > and it wants a NULL for one or more of its parameters,
> > what exactly is the structure of a NULL? A 32 bit
> > word full of zeros?
>
> You might get better answers if you explained why you want to know.
>
> If you're making a call from C++, you can just pass a null pointer
> value such as nullptr or NULL. The compiler needs to know how
> it's represented. You probably don't.

But knowing it can be useful, I use (void*) to cast integers and
unsigned integers for functions that require pointer parameters,
and if (parm) to test them.

Manfred

unread,
Dec 28, 2019, 2:11:30 PM12/28/19
to
If you are running 32 bit windows, then it uses only 32-bit pointers.

If you are running 64 bit windows, then it depends on the calling
process (as there exist 2 versions of kernel32.dll, one for 64bit
processes and one for 32bit processes).
If you are still using Perl, then this means the Perl interpreter, but I
guess the Perl doc should give some info on how to use pointers in
native calls.

Keith Thompson

unread,
Dec 28, 2019, 4:22:59 PM12/28/19
to
Why? Can you share some examples?

If a function takes a pointer parameter, you need to pass a pointer
value to it. There are cases where it might make sense to cast
an integer to void*, but they're rare. If you need to pass a null
pointer, use nullptr or NULL. (In some low-level code, you might
store pointer values in integers.) As for `if (parm)`, that's
valid for any scalar type.

Chris M. Thomasson

unread,
Dec 28, 2019, 7:02:39 PM12/28/19
to
On 12/28/2019 1:22 PM, Keith Thompson wrote:
> Ned Latham <nedl...@woden.valhalla.oz> writes:
>> Keith Thompson wrote:
>>> T writes:
>>>>
>>>> In C++, when you make a call to Windows Kernel32.dll
>>>> and it wants a NULL for one or more of its parameters,
>>>> what exactly is the structure of a NULL? A 32 bit
>>>> word full of zeros?
>>>
>>> You might get better answers if you explained why you want to know.
>>>
>>> If you're making a call from C++, you can just pass a null pointer
>>> value such as nullptr or NULL. The compiler needs to know how
>>> it's represented. You probably don't.
>>
>> But knowing it can be useful, I use (void*) to cast integers and
>> unsigned integers for functions that require pointer parameters,
>> and if (parm) to test them.
>
> Why? Can you share some examples?
>
> If a function takes a pointer parameter, you need to pass a pointer
> value to it. There are cases where it might make sense to cast
> an integer to void*, but they're rare. If you need to pass a null
> pointer, use nullptr or NULL. (In some low-level code, you might
> store pointer values in integers.) As for `if (parm)`, that's
> valid for any scalar type.
>

Fwiw, I remember using 0xDEADBEEF as a special place holder for a
pointer in some lock-free algorithms. The pointer would have the value
of 0xDEADBEEF in order to indicate a condition that was in progress to
the algorihtm.

T

unread,
Dec 28, 2019, 8:15:04 PM12/28/19
to
Thank you!

T

unread,
Dec 28, 2019, 8:17:05 PM12/28/19
to
On 2019-12-28 11:11, Manfred wrote:
> If you are still using Perl, then this means the Perl interpreter, but I
> guess the Perl doc should give some info on how to use pointers in
> native calls.

It does. Raku's documents are really badly written at the moment.

https://docs.perl6.org/language/nativecall#Basic_use_of_pointers

They are a migraine to figure out.

T

unread,
Dec 28, 2019, 8:17:53 PM12/28/19
to
On 2019-12-27 17:46, Bart wrote:
> At what level are you coding, assembly?

https://docs.raku.org/language/nativecall

Bart

unread,
Dec 28, 2019, 8:42:57 PM12/28/19
to
So, this seems to be (or was) Perl6, and it already has a foreign
function interface. Then you need to investigate how such calls are done
using Raku's FF interface. For example it says this:

"Note that a NULL string pointer can be passed by passing the Str type
object; a NULL return will also be represented by the type object."

Doesn't mean much to me, but in any case it's not really to do with C or
C++ (half of WinAPI was originally C but MS renamed all those C
interfaces as C++ at some point.)

I'm surprised there isn't a ready-made set of 'bindings' to WinAPI,
rather than having to create your own (there are some 10,000 WinAPI
functions plus 1000s of structs, types, macros and messages).

Even if you did know that a NULL pointer was passed as an all-zeros 32-
or 64-bit value or whatever, it would be unwise to go that low level;
you should use whatever Raku suggests is used as a null pointer.

T

unread,
Dec 28, 2019, 9:40:04 PM12/28/19
to
Perl 5 has a WinAPI, but Perl6/Raku does not yet.

Native Call's documentation is terrible. You have to experiment until
you get it right.

I do believe that to pass a NULL, you just put "$" without
the quotes as the variable to be passed. But I haven't
tested it yet. It is also undocumented.


Ned Latham

unread,
Dec 28, 2019, 11:37:22 PM12/28/19
to
Keith Thompson wrote:
> Ned Latham writes:
> > Keith Thompson wrote:
> > > T writes:
> > > >
> > > > In C++, when you make a call to Windows Kernel32.dll
> > > > and it wants a NULL for one or more of its parameters,
> > > > what exactly is the structure of a NULL? A 32 bit
> > > > word full of zeros?
> > >
> > > You might get better answers if you explained why you want to know.
> > >
> > > If you're making a call from C++, you can just pass a null pointer
> > > value such as nullptr or NULL. The compiler needs to know how
> > > it's represented. You probably don't.
> >
> > But knowing it can be useful, I use (void*) to cast integers and
> > unsigned integers for functions that require pointer parameters,
> > and if (parm) to test them.
>
> Why? Can you share some examples?

Why? In what way does the above need elucidation?

> If a function takes a pointer parameter, you need to pass a pointer
> value to it. There are cases where it might make sense to cast
> an integer to void*, but they're rare.

Irelevant.

> If you need to pass a null
> pointer, use nullptr or NULL.

Why? (void*) (well okay (defined_type*), actually) does perfectly well,
and it does away with the clumsiness of switching between constant
and variable.

> (In some low-level code, you might
> store pointer values in integers.)

Indeed.

> As for `if (parm)`, that's
> valid for any scalar type.

Precisely.

Ned Latham

unread,
Dec 28, 2019, 11:38:09 PM12/28/19
to
Chris M. Thomasson wrote in <qu8qej$q5p$3...@gioia.aioe.org>:
Good one.

Keith Thompson

unread,
Dec 29, 2019, 12:12:37 AM12/29/19
to
Ned Latham <nedl...@woden.valhalla.oz> writes:
> Keith Thompson wrote:
>> Ned Latham writes:
>> > Keith Thompson wrote:
>> > > T writes:
>> > > >
>> > > > In C++, when you make a call to Windows Kernel32.dll
>> > > > and it wants a NULL for one or more of its parameters,
>> > > > what exactly is the structure of a NULL? A 32 bit
>> > > > word full of zeros?
>> > >
>> > > You might get better answers if you explained why you want to know.
>> > >
>> > > If you're making a call from C++, you can just pass a null pointer
>> > > value such as nullptr or NULL. The compiler needs to know how
>> > > it's represented. You probably don't.
>> >
>> > But knowing it can be useful, I use (void*) to cast integers and
>> > unsigned integers for functions that require pointer parameters,
>> > and if (parm) to test them.
>>
>> Why? Can you share some examples?
>
> Why? In what way does the above need elucidation?

You indicated that it's useful to know how a null pointer is
represented. How is it useful? Most of the time, the representation
doesn't matter.

>> If a function takes a pointer parameter, you need to pass a pointer
>> value to it. There are cases where it might make sense to cast
>> an integer to void*, but they're rare.
>
> Irelevant.

Irrelevant to what exactly?

>> If you need to pass a null
>> pointer, use nullptr or NULL.
>
> Why? (void*) (well okay (defined_type*), actually) does perfectly well,
> and it does away with the clumsiness of switching between constant
> and variable.

Do you mean "(void*)0"? Yes, that's a valid null pointer constant, but
why do you prefer it to NULL or nullptr? What do you mean by "switching
between constant and variable"?

>> (In some low-level code, you might
>> store pointer values in integers.)
>
> Indeed.
>
>> As for `if (parm)`, that's
>> valid for any scalar type.
>
> Precisely.

Precisely what? If parm is of pointer type, `if (parm)` tests whether
it's a null pointer or not, regardless of how it's represented. You
seemed to be using that as an example of why it's useful to know how
pointers are represented. It isn't.

Perhaps I'm missing something. What exactly was your point?

Ned Latham

unread,
Dec 29, 2019, 5:46:07 AM12/29/19
to
Keith Thompson wrote:
> Ned Latham writes:
> > Keith Thompson wrote:
> > > Ned Latham writes:
> > > > Keith Thompson wrote:
> > > > > T writes:
> > > > > >
> > > > > > In C++, when you make a call to Windows Kernel32.dll
> > > > > > and it wants a NULL for one or more of its parameters,
> > > > > > what exactly is the structure of a NULL? A 32 bit
> > > > > > word full of zeros?
> > > > >
> > > > > You might get better answers if you explained why you want to know.
> > > > >
> > > > > If you're making a call from C++, you can just pass a null pointer
> > > > > value such as nullptr or NULL. The compiler needs to know how
> > > > > it's represented. You probably don't.
> > > >
> > > > But knowing it can be useful, I use (void*) to cast integers and
> > > > unsigned integers for functions that require pointer parameters,
> > > > and if (parm) to test them.
> > >
> > > Why? Can you share some examples?
> >
> > Why? In what way does the above need elucidation?
>
> You indicated that it's useful to know how a null pointer is
> represented. How is it useful? Most of the time, the representation
> doesn't matter.

Knowing it's useful in that it enables me to use it.

> > > If a function takes a pointer parameter, you need to pass a pointer
> > > value to it. There are cases where it might make sense to cast
> > > an integer to void*, but they're rare.
> >
> > Irrelevant.
>
> Irrelevant to what exactly?

Except for that last phrase "but they're rare", your statement amounts to
an acceptance (inadveratant, I'm sure) of what I'm saying. You agree that
"there are cases"; their rarity or otherwise is irrelevanbt.

> > > If you need to pass a null
> > > pointer, use nullptr or NULL.
> >
> > Why? (void*) (well okay (defined_type*), actually) does perfectly well,
> > and it does away with the clumsiness of switching between constant
> > and variable.
>
> Do you mean "(void*)0"?

Not particularly. (void*) applies safely to variables on systems where
sizeof(int) == sizeof(void*).

> Yes, that's a valid null pointer constant, but
> why do you prefer it to NULL or nullptr? What do you mean by "switching
> between constant and variable"?

Pointer arithmetic.

> > > (In some low-level code, you might
> > > store pointer values in integers.)
> >
> > Indeed.
> >
> > > As for `if (parm)`, that's
> > > valid for any scalar type.
> >
> > Precisely.
>
> Precisely what?

It's valid for pointers. If that's useful, use it.

> If parm is of pointer type, `if (parm)` tests whether
> it's a null pointer or not, regardless of how it's represented. You
> seemed to be using that as an example of why it's useful to know how
> pointers are represented. It isn't.
>
> Perhaps I'm missing something. What exactly was your point?

I've stated it in every post in this thread. Knowing how NUL is
represented can be useful.

Manfred

unread,
Dec 29, 2019, 11:53:04 AM12/29/19
to
I see that it says that perl6 provides a Pointer type that can hold
pointers.
The very last sentence says "Once again, type objects are used to
represent NULL pointers."
I don't know what "type objects" are in Perl (this kind of confusion
between types and objects is one of the reasons why I hate scripting
languages), but I guess this should mean something to someone more
familiar with that language.

T

unread,
Dec 29, 2019, 3:22:04 PM12/29/19
to
Hi Manfred,

The documentation is such rubbish.

What I had to find out through experimentation
was that Native Call creates the C NULL for you
when you pass it a zero. It begs the question
if you actually wanted to pass a numerical zero.

If you pass it an "type object", it errors out
on you (crappy documentation).

And if you are expecting to get a pointer back,
you won't. Native call extracts the value for you.
Again, crappy documentation.

Native Call also tacks on a chr(0) to a C String
automatically for you too. More crappy documentation.

When my programs hit over 4000 lines, I would not
refer to it as a "Scripting Language".

Raku a hybrid language. First it gets interpreted, then
the OPCODE gets compiled. It allows you to create
code TWICE as FAST as a pure compiled language, but
also runs TWICE as SLOW. (I am not smart enough
to program in C or C++ either.)

Thank you all for the help. I FINALLY have it
all figured out!

-T

Keith Thompson

unread,
Dec 29, 2019, 4:31:20 PM12/29/19
to
Ned Latham <nedl...@woden.valhalla.oz> writes:
> Keith Thompson wrote:
>> Ned Latham writes:
>> > Keith Thompson wrote:
>> > > Ned Latham writes:
>> > > > Keith Thompson wrote:
>> > > > > T writes:
>> > > > > >
>> > > > > > In C++, when you make a call to Windows Kernel32.dll
>> > > > > > and it wants a NULL for one or more of its parameters,
>> > > > > > what exactly is the structure of a NULL? A 32 bit
>> > > > > > word full of zeros?
>> > > > >
>> > > > > You might get better answers if you explained why you want to know.
>> > > > >
>> > > > > If you're making a call from C++, you can just pass a null pointer
>> > > > > value such as nullptr or NULL. The compiler needs to know how
>> > > > > it's represented. You probably don't.
>> > > >
>> > > > But knowing it can be useful, I use (void*) to cast integers and
>> > > > unsigned integers for functions that require pointer parameters,
>> > > > and if (parm) to test them.
>> > >
>> > > Why? Can you share some examples?
>> >
>> > Why? In what way does the above need elucidation?
>>
>> You indicated that it's useful to know how a null pointer is
>> represented. How is it useful? Most of the time, the representation
>> doesn't matter.
>
> Knowing it's useful in that it enables me to use it.

I'm about to give up on this conversation, since it seems unlikely to go
anywhere useful.

99% of the time, there is no good reason to care in C++ how a null
pointer, or any other pointer value, is represented. It's an
abstraction. You can write C++ code that uses null pointers, and you
haven't done anything unnecessarily tricky, your code will work
correctly on implementations with different representations.

How exactly does knowing how null pointers are represented make it
easier to use them?

>> > > If a function takes a pointer parameter, you need to pass a pointer
>> > > value to it. There are cases where it might make sense to cast
>> > > an integer to void*, but they're rare.
>> >
>> > Irrelevant.
>>
>> Irrelevant to what exactly?
>
> Except for that last phrase "but they're rare", your statement amounts to
> an acceptance (inadveratant, I'm sure) of what I'm saying. You agree that
> "there are cases"; their rarity or otherwise is irrelevanbt.

You've decided that rarity is irrelevant. Perhaps it is for whatever
you're talking about (I still haven't quite figured out what that is).
I acknowledge, of course, that there are some cases in very low-level
code where knowing pointer representation is useful. The rarity of
those cases is extremely relevant to what I'm talking about.

>> > > If you need to pass a null
>> > > pointer, use nullptr or NULL.
>> >
>> > Why? (void*) (well okay (defined_type*), actually) does perfectly well,
>> > and it does away with the clumsiness of switching between constant
>> > and variable.
>>
>> Do you mean "(void*)0"?
>
> Not particularly. (void*) applies safely to variables on systems where
> sizeof(int) == sizeof(void*).

What variables? Of what type(s)? Are you saying that something like
`(void*)42` is useful?

>> Yes, that's a valid null pointer constant, but
>> why do you prefer it to NULL or nullptr? What do you mean by "switching
>> between constant and variable"?
>
> Pointer arithmetic.

I still don't know the answer to my question. Perhaps an example would
help.

Please take a moment to consider that I really don't know what you're
talking about, and that perhaps that's because you haven't explained it
clearly.

Pointer arithmetic does not depend on the representation of pointers.
It's an abstraction defined in terms of the objects the pointers point
to. Of course the implementation depends on the representation, but if
you're not writing a compiler you *probably* don't need to care about
that.

I've worked on systems where this:
char *ptr = ...;
char *p1 = ptr + 1;
char *p2 = (char*)((int)ptr + 1);
would give p1 and p2 different values (and sizeof (int) == sizeof (char*)).

>> > > (In some low-level code, you might
>> > > store pointer values in integers.)
>> >
>> > Indeed.
>> >
>> > > As for `if (parm)`, that's
>> > > valid for any scalar type.
>> >
>> > Precisely.
>>
>> Precisely what?
>
> It's valid for pointers. If that's useful, use it.

Yes, of course. And it has nothing to do with pointer representation.
It doesn't support you claim that knowing how pointers are represented
is useful.

>> If parm is of pointer type, `if (parm)` tests whether
>> it's a null pointer or not, regardless of how it's represented. You
>> seemed to be using that as an example of why it's useful to know how
>> pointers are represented. It isn't.
>>
>> Perhaps I'm missing something. What exactly was your point?
>
> I've stated it in every post in this thread. Knowing how NUL is
> represented can be useful.

It's spelled NULL.

I don't dispute that it *can* be useful. I disagree that it's useful in
general. In particular, I can write code without knowing or caring how
a null pointer is represented, and that will work correctly under
different implementations that represent it differently.

Languages define abstractions precisely so programmers don't have to
worry about the underlying details.

James Kuyper

unread,
Dec 29, 2019, 8:20:25 PM12/29/19
to
On 12/29/19 5:45 AM, Ned Latham wrote:
> Keith Thompson wrote:
...
>> You indicated that it's useful to know how a null pointer is
>> represented. How is it useful? Most of the time, the representation
>> doesn't matter.
>
> Knowing it's useful in that it enables me to use it.

Can you give an example of code involving a null pointer that you could
not have used if you had not known how null pointers are represented? I
write code that deals correctly with null pointers all the time, and to
the best of my knowledge, not a single line of code I've ever written
would need a re-write if ported to a system which uses a different
representation for null pointers.

...
> I've stated it in every post in this thread. Knowing how NUL is
> represented can be useful.

I thought that this discussion was about NULL, or null pointers, or null
pointer constants. Knowing how NUL is represented is a very different
issue, and can be useful - and has nothing to do with any of those other
three things.

Ned Latham

unread,
Dec 29, 2019, 10:34:17 PM12/29/19
to
Keith Thompson wrote:

----snip----

> I don't dispute that it *can* be useful.

If it *can* be useful, then it *is* useful.

> I disagree that it's useful in
> general.

I gather you mean "widely useful". I say nothinbg about that.

----snip----

Ned Latham

unread,
Dec 29, 2019, 10:50:14 PM12/29/19
to
James Kuyper wrote:
> Ned Latham wrote:
> > Keith Thompson wrote:
> > >
> > > You indicated that it's useful to know how a null pointer is
> > > represented. How is it useful? Most of the time, the representation
> > > doesn't matter.
> >
> > Knowing it's useful in that it enables me to use it.
>
> Can you give an example of code involving a null pointer that you could
> not have used if you had not known how null pointers are represented? I
> write code that deals correctly with null pointers all the time, and to
> the best of my knowledge, not a single line of code I've ever written
> would need a re-write if ported to a system which uses a different
> representation for null pointers.

http://www.users.on.net/~nedlatham/Software/mclib/Documents/sourcecode.html

Check AVLC and ListC, also read
http://www.users.on.net/~nedlatham/Software/mclib/Documents/mclists.html

The original intention was widespread compatibility, but when the
versionitis set in that faded. I won't be programming for other
than Linux anyway. When the versionitis conflicts with my standards
or violates my requirements, I'll maintain my development machine
at previous sofware version(s).

----twisted typo twittery snipped----

Keith Thompson

unread,
Dec 30, 2019, 1:47:01 AM12/30/19
to
Ned Latham <nedl...@woden.valhalla.oz> writes:
> James Kuyper wrote:
>> Ned Latham wrote:
>> > Keith Thompson wrote:
>> > >
>> > > You indicated that it's useful to know how a null pointer is
>> > > represented. How is it useful? Most of the time, the representation
>> > > doesn't matter.
>> >
>> > Knowing it's useful in that it enables me to use it.
>>
>> Can you give an example of code involving a null pointer that you could
>> not have used if you had not known how null pointers are represented? I
>> write code that deals correctly with null pointers all the time, and to
>> the best of my knowledge, not a single line of code I've ever written
>> would need a re-write if ported to a system which uses a different
>> representation for null pointers.
>
> http://www.users.on.net/~nedlatham/Software/mclib/Documents/sourcecode.html
>
> Check AVLC and ListC, also read
> http://www.users.on.net/~nedlatham/Software/mclib/Documents/mclists.html

Can you give a *succinct* example? I'm not going to spend the time it
would take to read that.

Of course you *can* write code that depends on the representation of a
null pointer, but there is rarely a good reason to do so.

[...]

Keith Thompson

unread,
Dec 30, 2019, 1:48:26 AM12/30/19
to
Ned Latham <nedl...@woden.valhalla.oz> writes:
> Keith Thompson wrote:
>
> ----snip----
>
>> I don't dispute that it *can* be useful.
>
> If it *can* be useful, then it *is* useful.

That must be why English doesn't distinguish between "can be" and "is".
Oh, wait, it does.

>> I disagree that it's useful in
>> general.
>
> I gather you mean "widely useful". I say nothinbg about that.

One clear example that you can post here would be helpful.

David Brown

unread,
Dec 30, 2019, 4:25:34 AM12/30/19
to
On 30/12/2019 07:46, Keith Thompson wrote:
> Ned Latham <nedl...@woden.valhalla.oz> writes:
>> James Kuyper wrote:
>>> Ned Latham wrote:
>>>> Keith Thompson wrote:
>>>>>
>>>>> You indicated that it's useful to know how a null pointer is
>>>>> represented. How is it useful? Most of the time, the representation
>>>>> doesn't matter.
>>>>
>>>> Knowing it's useful in that it enables me to use it.
>>>
>>> Can you give an example of code involving a null pointer that you could
>>> not have used if you had not known how null pointers are represented? I
>>> write code that deals correctly with null pointers all the time, and to
>>> the best of my knowledge, not a single line of code I've ever written
>>> would need a re-write if ported to a system which uses a different
>>> representation for null pointers.
>>
>> http://www.users.on.net/~nedlatham/Software/mclib/Documents/sourcecode.html
>>
>> Check AVLC and ListC, also read
>> http://www.users.on.net/~nedlatham/Software/mclib/Documents/mclists.html
>
> Can you give a *succinct* example? I'm not going to spend the time it
> would take to read that.
>

I had a quick look at the code - for the sake of your sanity, don't read
it. I don't know what language Ned is trying to use, but it is not C++
as other people know it. (Hint - it is full of macros like WHILE and IF
and the like, which are not defined anywhere. And you know how C++ has
templates so that you can write container classes in a clear, type-safe
and efficient manner rather than the simple but riskier and less
efficient C-style use of void* pointers everywhere? And it has RAII for
convenient resource handling? New and delete rather than malloc and
free? Ned doesn't.)

I didn't see any relevance of the the representation of null pointers in
the code. But maybe I didn't look hard enough. Certainly he has
managed to make enumeration constants held in a CHAR type, bitfield
structs to hold two 16-bit integers, and I gave up trying to comprehend
his "string" class.)

Ned Latham

unread,
Dec 30, 2019, 5:19:59 AM12/30/19
to
Keith Thompson wrote:
> Ned Latham writes:
> > James Kuyper wrote:
> > > Ned Latham wrote:
> > > > Keith Thompson wrote:
> > > > >
> > > > > You indicated that it's useful to know how a null pointer is
> > > > > represented. How is it useful? Most of the time, the representation
> > > > > doesn't matter.
> > > >
> > > > Knowing it's useful in that it enables me to use it.
> > >
> > > Can you give an example of code involving a null pointer that you could
> > > not have used if you had not known how null pointers are represented? I
> > > write code that deals correctly with null pointers all the time, and to
> > > the best of my knowledge, not a single line of code I've ever written
> > > would need a re-write if ported to a system which uses a different
> > > representation for null pointers.
> >
> > http://www.users.on.net/~nedlatham/Software/mclib/Documents/sourcecode.html
> >
> > Check AVLC and ListC, also read
> > http://www.users.on.net/~nedlatham/Software/mclib/Documents/mclists.html
>
> Can you give a *succinct* example? I'm not going to spend the time it
> would take to read that.

What you've got is working code and documentation describing it. The AVLC
Specification document details three funcions that take void* parameters
and also return void*, Extract(), Find(), Insert().

----snip----

Ned Latham

unread,
Dec 30, 2019, 6:20:51 AM12/30/19
to
David Brown wrote:
> Keith Thompson wrote:
> > Ned Latham writes:
> > > James Kuyper wrote:
> > > > Ned Latham wrote:
> > > > > Keith Thompson wrote:
> > > > > >
> > > > > > You indicated that it's useful to know how a null pointer is
> > > > > > represented. How is it useful? Most of the time, the representation
> > > > > > doesn't matter.
> > > > >
> > > > > Knowing it's useful in that it enables me to use it.
> > > >
> > > > Can you give an example of code involving a null pointer that you could
> > > > not have used if you had not known how null pointers are represented? I
> > > > write code that deals correctly with null pointers all the time, and to
> > > > the best of my knowledge, not a single line of code I've ever written
> > > > would need a re-write if ported to a system which uses a different
> > > > representation for null pointers.
> > >
> > > http://www.users.on.net/~nedlatham/Software/mclib/Documents/sourcecode.html
> > >
> > > Check AVLC and ListC, also read
> > > http://www.users.on.net/~nedlatham/Software/mclib/Documents/mclists.html
> >
> > Can you give a *succinct* example? I'm not going to spend the time it
> > would take to read that.
> >
>
> I had a quick look at the code - for the sake of your sanity, don't read
> it.

Well, if you're not going to read any documentation, why bother indeed.

> I don't know what language Ned is trying to use,

Using, David. mclib is a working C++ library. Has been for at least ten
years.

> but it is not C++
> as other people know it.

The documentation tells you that. And why.

> (Hint - it is full of macros like WHILE and IF
> and the like, which are not defined anywhere.

Don't be stupider than you have to be, David.

> And you know how C++ has
> templates so that you can write container classes in a clear, type-safe
> and efficient manner rather than the simple but riskier and less
> efficient C-style use of void* pointers everywhere?

The documentation would have told you that AVLC and ListC are designed to
be totally independent of type (past, present and future). Pointers can do
that; templates cannot. They're a code bloat idea, anyway.

> And it has RAII for
> convenient resource handling? New and delete rather than malloc and
> free? Ned doesn't.)

Those are design decisions too, idiot. The C++ library throws exceptions.
Exceptions are evil, especially in low-level code.

And BTW, it's calloc(), not malloc(). Linux malloc() has a tendency to
return "optimistic" pointers, which for my purposes is an unreliable
behaviour.

----snip----

Öö Tiib

unread,
Dec 30, 2019, 6:25:37 AM12/30/19
to
On Monday, 30 December 2019 08:47:01 UTC+2, Keith Thompson wrote:
> Ned Latham <nedl...@woden.valhalla.oz> writes:
> >
> > http://www.users.on.net/~nedlatham/Software/mclib/Documents/sourcecode.html
> >
> > Check AVLC and ListC, also read
> > http://www.users.on.net/~nedlatham/Software/mclib/Documents/mclists.html

It is not simple to find apprentices for a master with such style.

> Can you give a *succinct* example? I'm not going to spend the time it
> would take to read that.

I have seen lot of code that assumes that null pointer has all bits clear.
Most typical case is that contents of some byte buffer is zeroed. Can be
calloc, memset, resize of byte vector or default-initialized byte array. As
next step it is assumed that (properly aligned) bytes in such buffer can
be now treated as nullptr.

> Of course you *can* write code that depends on the representation of a
> null pointer, but there is rarely a good reason to do so.

The usual reason is ignorance. Rare people know details of ABI of C++
for one or other platform and next to no one has expertise in extent
of allowable by standard freedoms in ABI. Literal 0 is required to be
null pointer constant and incorrect assumption that null pointer constant
is required to have all bits clear is therefore trivial to make.

It is often not expensive to rewrite such places into conforming and it
likely does not affect any performance but fixes of never-manifesting
defects can be intricate to sell and last minute changes can cause
actual defects (in non-trivial code on about 50% of cases IME). So
in review I typically request unit tests and static asserts about
platform-specific assumptions instead of rewrite.

James Kuyper

unread,
Dec 30, 2019, 9:03:31 AM12/30/19
to
Ned Latham wrote:
> James Kuyper wrote:
...
> > Can you give an example of code involving a null pointer that you could
> > not have used if you had not known how null pointers are represented? I
> > write code that deals correctly with null pointers all the time, and to
> > the best of my knowledge, not a single line of code I've ever written
> > would need a re-write if ported to a system which uses a different
> > representation for null pointers.

> http://www.users.on.net/~nedlatham/Software/mclib/Documents/sourcecode.html

> Check AVLC and ListC, also read
> http://www.users.on.net/~nedlatham/Software/mclib/Documents/mclists.html

That is not the kind of response I was asking for. Let me be more explicit:
I'm looking for a single C++ construct, from a single line of code, that
you were only able to use because of what you know about how null pointers
are represented on the target implementation. That is, inherently, a
construct that would not produce the desired result if the code were ported
to an implementation that uses a different way to represent null pointers.
It's fine if you need to provide additional lines of code, or even system
documentation, to provide the proper context for that construct. However,
I need you to actually identify the particular construct you're referring
to. Can you give me the exact location in that body of code of at least
one such construct? Better yet, could you quote that line of code?

David Brown

unread,
Dec 30, 2019, 11:24:43 AM12/30/19
to
You didn't link to documentation - you linked to the source code. The
source code was, of course, the important part for the discussion. (I
found the document pages too.)

>
>> I don't know what language Ned is trying to use,
>
> Using, David. mclib is a working C++ library. Has been for at least ten
> years.
>

I only looked at the source code you linked - it is not complete,
because it is written in a sort-of C, sort-of C++, sort-of something
else mix using your own macros.

>> but it is not C++
>> as other people know it.
>
> The documentation tells you that. And why.

No, it does not.

>
>> (Hint - it is full of macros like WHILE and IF
>> and the like, which are not defined anywhere.
>
> Don't be stupider than you have to be, David.

They are not defined in the source code you linked. They are defined in
the file "mcdef.h", which was not in the links (it is in the tarball
that can be found by a little digging from your links).

There are few thinks more irritating to programmers than some nitwit who
thinks it helps to make one programming language look like another.
Macros to try to make your C or C++ code like BASIC are /not/ a good
idea, and never have been.


>
>> And you know how C++ has
>> templates so that you can write container classes in a clear, type-safe
>> and efficient manner rather than the simple but riskier and less
>> efficient C-style use of void* pointers everywhere?
>
> The documentation would have told you that AVLC and ListC are designed to
> be totally independent of type (past, present and future). Pointers can do
> that; templates cannot. They're a code bloat idea, anyway.

Had you linked to the documentation, it would have told me that. It
says nothing about /why/ that might be a useful idea. (A reasonable
answer would be "the code is from 1995, when C++ compilers had limited
and inefficient support for templates".)


>
>> And it has RAII for
>> convenient resource handling? New and delete rather than malloc and
>> free? Ned doesn't.)
>
> Those are design decisions too, idiot. The C++ library throws exceptions.
> Exceptions are evil, especially in low-level code.

RAII is orthogonal to exceptions. You can use one feature without the
other, though they work well together.

I can appreciate that your code was written before non-throwing "new"
was widely available. Some of your design decisions are reasonable
enough for code from 1995 - but hardly examples of how to write C++ in
this generation.


>
> And BTW, it's calloc(), not malloc(). Linux malloc() has a tendency to
> return "optimistic" pointers, which for my purposes is an unreliable
> behaviour.
>

Yes, you mentioned that in your documentation. It was one of many
incorrect statements.

David Brown

unread,
Dec 30, 2019, 11:27:50 AM12/30/19
to
Even though you apparently have no intention of answering Keith's
questions sensibly, could you at least say why you think a function
returning void* is dependent on the representation of null pointers?

Your documentation says your code relies on void* being the same size as
int. I didn't see anything in the code that actually depends on that
(but I have not gone through it in detail) - but that bears no direct
relationship on the representation of null pointer constants.


Ben Bacarisse

unread,
Dec 30, 2019, 1:16:34 PM12/30/19
to
Ned Latham <nedl...@woden.valhalla.oz> writes:

> David Brown wrote:
<cut>
>> [...] New and delete rather than malloc and free?

I suspect this is the heart of the problem.

> Those are design decisions too, idiot. The C++ library throws exceptions.
> Exceptions are evil, especially in low-level code.
>
> And BTW, it's calloc()

You assume that null pointers are represented with all-bits-zero because
you want to use calloc, and you want to use calloc because you think new
will throw an exception. (If you know about non-throwing new then I
can't see any reason for not using it, thereby allowing null pointers to
dealt with by a constructor as C++ intended.)

Also your test for null pointers being all-bits-zero (as provided by
calloc) is flawed:

#ifndef NULL
#define NULL 0
#elif (NULL != 0)
#error NULL is defined as non-zero!
#endif

NULL will always compare == 0, even when null pointers do not have all
bits zero.

--
Ben.

Keith Thompson

unread,
Dec 30, 2019, 1:45:32 PM12/30/19
to
Ben Bacarisse <ben.u...@bsb.me.uk> writes:
> Ned Latham <nedl...@woden.valhalla.oz> writes:
[...]
>> Those are design decisions too, idiot. The C++ library throws exceptions.
>> Exceptions are evil, especially in low-level code.
>>
>> And BTW, it's calloc()
>
> You assume that null pointers are represented with all-bits-zero because
> you want to use calloc, and you want to use calloc because you think new
> will throw an exception. (If you know about non-throwing new then I
> can't see any reason for not using it, thereby allowing null pointers to
> dealt with by a constructor as C++ intended.)

Is that the whole point of showing us that code, that it depends
on a null pointer being represented as all-bits-zero because it
uses calloc()? I wonder why Ned didn't just say so rather than
sending us on a wild goose chase digging through some online code.

I'll probably never know, because I won't waste my time talking to
someone who calls people idiots.

I can imagine that kind of thing not being entirely a bad idea in
code that's not intended to be portable. Using memset or calloc
while assuming that null pointers (and floating-point zeros,
if applicable) are represented as all-bits-zero is strictly not
portable, but it's likely good enough for target-specific code.
I'd still try to avoid that assumption unless I had a pretty good
reason to depend on it, and I'd be more likely to do something
like that in C than in C++. If I wanted to initialize a structure
to zeros, I'd rather use a { 0 } initializer than anything that
depends on representation.

I suspect Ned will take this as proof that I agree with him.
For the record, I don't.

Ned Latham

unread,
Dec 30, 2019, 6:01:18 PM12/30/19
to
No. get off your arese and look.

Ned Latham

unread,
Dec 30, 2019, 6:22:27 PM12/30/19
to
David Brown wrote:
> Ned Latham wrote:
>> David Brown wrote:
>>> Keith Thompson wrote:
>>>> Ned Latham writes:

----snip----

> I only looked at the source code you linked - it is not complete,

Bullshit.

> because it is written in a sort-of C, sort-of C++, sort-of something
> else mix using your own macros.

That's noi reason for saying "incomplete".,

>>> but it is not C++
>>> as other people know it.
>>
>> The documentation tells you that. And why.
>
> No, it does not.

Don't lie to me about what I wrote, you fuck.

>>
>>> (Hint - it is full of macros like WHILE and IF
>>> and the like, which are not defined anywhere.
>>
>> Don't be stupider than you have to be, David.
>
> They are not defined in the source code you linked.

So? The statement is dead stupid.

> They are defined in
> the file "mcdef.h", which was not in the links (it is in the tarball
> that can be found by a little digging from your links).

There's a link to it in the documentation.

> There are few thinks more irritating to programmers than some nitwit who
> thinks it helps to make one programming language look like another.
> Macros to try to make your C or C++ code like BASIC are /not/ a good
> idea, and never have been.

"BASIC"? You're a moron.

>>> And you know how C++ has
>>> templates so that you can write container classes in a clear, type-safe
>>> and efficient manner rather than the simple but riskier and less
>>> efficient C-style use of void* pointers everywhere?
>>
>> The documentation would have told you that AVLC and ListC are designed to
>> be totally independent of type (past, present and future). Pointers can do
>> that; templates cannot. They're a code bloat idea, anyway.
>
> Had you linked to the documentation, it would have told me that.

Hmph. All you had to do to see the whole site is use BS and ENTER in
the location bar.

> It says nothing about /why/ that might be a useful idea.

You're insane. Why would type-indepedence *not* be useful?

----idiocy snipped----

>>> And it has RAII for
>>> convenient resource handling? New and delete rather than malloc and
>>> free? Ned doesn't.)
>>
>> Those are design decisions too, idiot. The C++ library throws exceptions.
>> Exceptions are evil, especially in low-level code.
>
> RAII is orthogonal to exceptions.

It's bloat.

> You can use one feature without the
> other, though they work well together.
>
> I can appreciate that your code was written before non-throwing "new"
> was widely available. Some of your design decisions are reasonable
> enough for code from 1995 - but hardly examples of how to write C++ in
> this generation.

Mclib's not about C++.

>> And BTW, it's calloc(), not malloc(). Linux malloc() has a tendency to
>> return "optimistic" pointers, which for my purposes is an unreliable
>> behaviour.
>
> Yes, you mentioned that in your documentation. It was one of many
> incorrect statements.

Dream on, Bozo.

Ned Latham

unread,
Dec 30, 2019, 6:30:01 PM12/30/19
to
Keith Thompson wrote:

----snip----

> Is that the whole point of showing us that code, that it depends
> on a null pointer being represented as all-bits-zero because it
> uses calloc()?

No. Try reading with your eyes open.

Idiot.

> I wonder why Ned didn't just say so rather than
> sending us on a wild goose chase digging through some online code.
>
> I'll probably never know, because I won't waste my time talking to
> someone who calls people idiots.

Do you waste time talking to people who misrepresent what they've been
given and then sneer at it?

----snip----

James Kuyper

unread,
Dec 30, 2019, 9:43:04 PM12/30/19
to
On 12/30/19 6:01 PM, Ned Latham wrote:
> James Kuyper wrote:
>> Ned Latham wrote:
...
>>> http://www.users.on.net/~nedlatham/Software/mclib/Documents/sourcecode.html
>>
>>> Check AVLC and ListC, also read
>>> http://www.users.on.net/~nedlatham/Software/mclib/Documents/mclists.html
>>
>> That is not the kind of response I was asking for. Let me be more explicit:
>> I'm looking for a single C++ construct, from a single line of code, that
>> you were only able to use because of what you know about how null pointers
>> are represented on the target implementation. That is, inherently, a
>> construct that would not produce the desired result if the code were ported
>> to an implementation that uses a different way to represent null pointers.
>> It's fine if you need to provide additional lines of code, or even system
>> documentation, to provide the proper context for that construct. However,
>> I need you to actually identify the particular construct you're referring
>> to. Can you give me the exact location in that body of code of at least
>> one such construct? Better yet, could you quote that line of code?
>
> No. get off your arese and look.

Why? It shouldn't take you more than a few seconds to honor my request,
while it might take me hours to honor yours.
The fundamental problem is that I won't even necessarily recognize what
you're referring to, even if it's staring me in the face. There's a
pretty good chance that what you think is code that depends upon the
representation of null pointers is, in fact, not so dependent.
Alternatively, it might be code that I incorrectly think has no such
dependence - either way, I won't recognize it when I see it. However, if
you would just identify the particular code you're talking about, which
should only take you a few seconds, it might save me hours of possibly
fruitless searching, and we can move on to the discussion of whether or
not you're correct, and whether or not it was actually necessary to
write such code.

Keith Thompson

unread,
Dec 31, 2019, 12:49:02 AM12/31/19
to
Ned Latham <nedl...@woden.valhalla.oz> writes:
> Keith Thompson wrote:
> ----snip----
>
>> Is that the whole point of showing us that code, that it depends
>> on a null pointer being represented as all-bits-zero because it
>> uses calloc()?
>
> No. Try reading with your eyes open.
>
> Idiot.

It's not worth my time to read your code to try (and quite possibly
fail) to figure out what you're talking about. And it's no longer
worth my time to interact with you at all.

*Plonk*

[...]

Ned Latham

unread,
Dec 31, 2019, 7:03:46 AM12/31/19
to
James Kuyper wrote:

----snip----

> The fundamental problem is that I won't even necessarily recognize what
> you're referring to, even if it's staring me in the face. There's a
> pretty good chance that what you think is code that depends upon the
> representation of null pointers is, in fact, not so dependent.

I don't know why you haven't already got it. If NULL == 0 the same
logic can be used with pointers as with integers and all their bitwidth
lookalikes and all the functions that require or return those types.
Tests like

if (!(array=calloc(hemeny,sizeof(arrayrcrd)))) // then deal with OOM.

wouldn't work correctly otherwise.

Knowing the way NULL is represented can be useful.

----snip----

David Brown

unread,
Dec 31, 2019, 7:57:20 AM12/31/19
to
On 31/12/2019 00:22, Ned Latham wrote:
> David Brown wrote:
>> Ned Latham wrote:
>>> David Brown wrote:
>>>> Keith Thompson wrote:
>>>>> Ned Latham writes:
>
> ----snip----
>
>> I only looked at the source code you linked - it is not complete,
>
> Bullshit.
>
>> because it is written in a sort-of C, sort-of C++, sort-of something
>> else mix using your own macros.
>
> That's noi reason for saying "incomplete".,

That is not why I said it was incomplete. I said it was incomplete
because you linked to some source code that relied on non-standard
headers that were not included in your links.

>
>>>> but it is not C++
>>>> as other people know it.
>>>
>>> The documentation tells you that. And why.
>>
>> No, it does not.
>
> Don't lie to me about what I wrote, you fuck.
>

Throwing your toys out the pram does not help your argument.

>>>
>>>> (Hint - it is full of macros like WHILE and IF
>>>> and the like, which are not defined anywhere.
>>>
>>> Don't be stupider than you have to be, David.
>>
>> They are not defined in the source code you linked.
>
> So? The statement is dead stupid.

It is /correct/. You said "look at the source code in this link", and I
did. I saw it was incomplete, and said so. I could certainly make a
reasonable guess about how you defined macros like "WHILE", but I could
not be sure what else might be missing. And there is a limit to how
much effort I'll put in deciphering spaghetti that mixes includes and
conditional compilation like your code.

>
>> They are defined in
>> the file "mcdef.h", which was not in the links (it is in the tarball
>> that can be found by a little digging from your links).
>
> There's a link to it in the documentation.

That would be the documentation that was not included in the original
links, but which I found by digging around?

Perhaps you sent the wrong links, or have not looked at the links for
some time.

>
>> There are few thinks more irritating to programmers than some nitwit who
>> thinks it helps to make one programming language look like another.
>> Macros to try to make your C or C++ code like BASIC are /not/ a good
>> idea, and never have been.
>
> "BASIC"? You're a moron.

IF no tail THEN return NULL;

It's not quite BASIC, but it's C code with macros to make it look like
BASIC.

Maybe you had another language in mind, rather than BASIC - but not C or
C++.


>
>>>> And you know how C++ has
>>>> templates so that you can write container classes in a clear, type-safe
>>>> and efficient manner rather than the simple but riskier and less
>>>> efficient C-style use of void* pointers everywhere?
>>>
>>> The documentation would have told you that AVLC and ListC are designed to
>>> be totally independent of type (past, present and future). Pointers can do
>>> that; templates cannot. They're a code bloat idea, anyway.
>>
>> Had you linked to the documentation, it would have told me that.
>
> Hmph. All you had to do to see the whole site is use BS and ENTER in
> the location bar.

It didn't take me much digging - I did not suggest it was difficult to
find. But if you had intended for people to read the documentation it
would have made sense to link to it.

>
>> It says nothing about /why/ that might be a useful idea.
>
> You're insane. Why would type-indepedence *not* be useful?
>

When it leads to inefficient and unsafe code, like yours?

> ----idiocy snipped----
>
>>>> And it has RAII for
>>>> convenient resource handling? New and delete rather than malloc and
>>>> free? Ned doesn't.)
>>>
>>> Those are design decisions too, idiot. The C++ library throws exceptions.
>>> Exceptions are evil, especially in low-level code.
>>
>> RAII is orthogonal to exceptions.
>
> It's bloat.

Please explain.

>
>> You can use one feature without the
>> other, though they work well together.
>>
>> I can appreciate that your code was written before non-throwing "new"
>> was widely available. Some of your design decisions are reasonable
>> enough for code from 1995 - but hardly examples of how to write C++ in
>> this generation.
>
> Mclib's not about C++.
>

So you agree it is not written in normal C++ ?

>>> And BTW, it's calloc(), not malloc(). Linux malloc() has a tendency to
>>> return "optimistic" pointers, which for my purposes is an unreliable
>>> behaviour.
>>
>> Yes, you mentioned that in your documentation. It was one of many
>> incorrect statements.
>
> Dream on, Bozo.
>

No, thanks, I will try to leave it at that - I have no plans to try to
list your mistakes. People can read your posts in this thread and guess.

Ned Latham

unread,
Dec 31, 2019, 8:33:39 AM12/31/19
to
David Brown wrote:
> Ned Latham wrote:
> > David Brown wrote:

----snip----

> > > I only looked at the source code you linked - it is not complete,
> >
> > Bullshit.
> >
> > > because it is written in a sort-of C, sort-of C++, sort-of something
> > > else mix using your own macros.
> >
> > That's noi reason for saying "incomplete".,
>
> That is not why I said it was incomplete. I said it was incomplete
> because you linked to some source code that relied on non-standard
> headers that were not included in your links.

That's another lie. And a really stupid one. Here's your statement as
it was before I split it for reply:

"I only looked at the source code you linked - it is not complete,
because it is written in a sort-of C, sort-of C++, sort-of something
else mix using your own macros."

You're a dimwit trying to cover your stupidity with lies. You'll
have much geater success if the only person you try to fool is
you.

----snip----

Öö Tiib

unread,
Dec 31, 2019, 9:17:32 AM12/31/19
to
On Tuesday, 31 December 2019 14:03:46 UTC+2, Ned Latham wrote:
> James Kuyper wrote:
>
> ----snip----
>
> > The fundamental problem is that I won't even necessarily recognize what
> > you're referring to, even if it's staring me in the face. There's a
> > pretty good chance that what you think is code that depends upon the
> > representation of null pointers is, in fact, not so dependent.
>
> I don't know why you haven't already got it. If NULL == 0 the same
> logic can be used with pointers as with integers and all their bitwidth
> lookalikes and all the functions that require or return those types.

[conv.ptr] "A null pointer constant is an integer literal with value
zero or a prvalue of type std::nullptr_t."

It does nowhere say that null pointer constant has no bits set only
that integer literal 0 is useful as it.

> Tests like
>
> if (!(array=calloc(hemeny,sizeof(arrayrcrd)))) // then deal with OOM.
>
> wouldn't work correctly otherwise.

That is addressed by different place of standard:
[conv.bool]
"A zero value, null pointer value, or null member pointer value is
converted to false; any other value is converted to true."

It does not say that bit-wise checks are made, if it contains null
pointer then it is converted to false regardless if null pointer
has all bits clear, or some, or none.

> Knowing the way NULL is represented can be useful.

You were asked example of it ... is it so hard to produce one?

David Brown

unread,
Dec 31, 2019, 9:45:11 AM12/31/19
to
Ah, the old "take stuff out of context and then sprinkle in wild
insults" ploy. Yes, I can clearly see how that changes your incomplete
code into complete code.

Your code was written using pointless fake-BASIC macros. Those were not
defined anywhere in the code you linked. Therefore your code was
incomplete.

(There might be all sorts of other things missing - or it might be
otherwise complete. I haven't checked.)


Chris Vine

unread,
Dec 31, 2019, 10:21:19 AM12/31/19
to
You have a point so far as concerns, say, memset'ing structs of
trivial type to all-bits-zero where those structs contain pointers
which you want to be NULL (should your code actually do that). But you
are completely wrong in your example above. 'array' will be a null
pointer constant if calloc fails, and the test for falsity will work
correctly irrespective of whether the null pointer constant is
signalled by all-bits-zero.

You have something wrong with your mental image of this.

Ned Latham

unread,
Dec 31, 2019, 11:46:46 AM12/31/19
to
嘱 Tiib wrote:
> Ned Latham wrote:

----snip----

> > Tests like
> >
> > if (!(array=calloc(hemeny,sizeof(arrayrcrd)))) // then deal with OOM.
> >
> > wouldn't work correctly otherwise.
>
> That is addressed by different place of standard:
> [conv.bool]
> "A zero value, null pointer value, or null member pointer value is
> converted to false; any other value is converted to true."

News to me. Might be because I'm a lazy reader or because my references
are out of date: Kernigan and Ritchie for C (ANSI 2) and Stroustrup
(Edition 3) for C++. Both 1990s.

> It does not say that bit-wise checks are made,

If NULL == 0, bitwise checks aren't required, just a check of the
Z flag of the register that received the return.

> if it contains null
> pointer then it is converted to false regardless if null pointer
> has all bits clear, or some, or none.

It's a good, portable way of applying logic to pointer values.

> > Knowing the way NULL is represented can be useful.
>
> You were asked example of it ... is it so hard to produce one?

int, i, j;

if (i - j == NULL) // then do whatever.

Melzzzzz

unread,
Dec 31, 2019, 11:57:47 AM12/31/19
to
On 2019-12-31, Ned Latham <nedl...@woden.valhalla.oz> wrote:
>
>> It does not say that bit-wise checks are made,
>
> If NULL == 0, bitwise checks aren't required, just a check of the
> Z flag of the register that received the return.

0 is converted to NULL pointer.

>
>> if it contains null
>> pointer then it is converted to false regardless if null pointer
>> has all bits clear, or some, or none.
>
> It's a good, portable way of applying logic to pointer values.
>
>> > Knowing the way NULL is represented can be useful.
>>
>> You were asked example of it ... is it so hard to produce one?
>
> int, i, j;
>
> if (i - j == NULL) // then do whatever.

except that this does not compiles. Imlicit conversion of int to pointer
is not done...



--
press any key to continue or any other to quit...
U ničemu ja ne uživam kao u svom statusu INVALIDA -- Zli Zec
Svi smo svedoci - oko 3 godine intenzivne propagande je dovoljno da jedan narod poludi -- Zli Zec
Na divljem zapadu i nije bilo tako puno nasilja, upravo zato jer su svi
bili naoruzani. -- Mladen Gogala

David Brown

unread,
Dec 31, 2019, 12:15:32 PM12/31/19
to
On 31/12/2019 17:57, Melzzzzz wrote:
> On 2019-12-31, Ned Latham <nedl...@woden.valhalla.oz> wrote:
>>
>>> It does not say that bit-wise checks are made,
>>
>> If NULL == 0, bitwise checks aren't required, just a check of the
>> Z flag of the register that received the return.
>
> 0 is converted to NULL pointer.
>
>>
>>> if it contains null
>>> pointer then it is converted to false regardless if null pointer
>>> has all bits clear, or some, or none.
>>
>> It's a good, portable way of applying logic to pointer values.
>>
>>>> Knowing the way NULL is represented can be useful.
>>>
>>> You were asked example of it ... is it so hard to produce one?
>>
>> int, i, j;
>>
>> if (i - j == NULL) // then do whatever.
>
> except that this does not compiles. Imlicit conversion of int to pointer
> is not done...
>

It might compile - "NULL" can be defined as "#define NULL 0" rather
than, say, "((void*) 0)".

It is not in any way dependent on the representation of null pointers,
as you probably know.

Ned Latham

unread,
Dec 31, 2019, 12:21:59 PM12/31/19
to
Melzzzzz wrote:
> Ned Latham wrote:
> > 嘱 Tiib wrote:

----snip----

> > > You were asked example of it ... is it so hard to produce one?
> >
> > int i, j;
> >
> > if (i - j == NULL) // then do whatever.
>
> except that this does not compiles. Imlicit conversion of int to pointer
> is not done...

Ok. if ((void*)(i - j) == NULL) // then do whatever.

Chris Vine

unread,
Dec 31, 2019, 12:27:35 PM12/31/19
to
On Tue, 31 Dec 2019 10:46:30 -0600
Ned Latham <nedl...@woden.valhalla.oz> wrote:
> Öö Tiib wrote:
[snip]
> > That is addressed by different place of standard:
> > [conv.bool]
> > "A zero value, null pointer value, or null member pointer value is
> > converted to false; any other value is converted to true."
>
> News to me. Might be because I'm a lazy reader or because my references
> are out of date: Kernigan and Ritchie for C (ANSI 2) and Stroustrup
> (Edition 3) for C++. Both 1990s.
>
> > It does not say that bit-wise checks are made,
>
> If NULL == 0, bitwise checks aren't required, just a check of the
> Z flag of the register that received the return.

'NULL == 0' will always evaluate to true, by virtue of the definition
of NULL. The bit pattern of the integer literal 0 as null pointer
constant may be different from its bit pattern as an integer, so your
check is meaningless.

James Kuyper

unread,
Dec 31, 2019, 1:27:52 PM12/31/19
to
Ned Latham wrote:
> James Kuyper wrote:
>
> ----snip----

> > The fundamental problem is that I won't even necessarily recognize what
> > you're referring to, even if it's staring me in the face. There's a
> > pretty good chance that what you think is code that depends upon the
> > representation of null pointers is, in fact, not so dependent.
>
> I don't know why you haven't already got it. If NULL == 0 the same
> logic can be used with pointers as with integers and all their bitwidth
> lookalikes and all the functions that require or return those types.

NULL is absolutely guaranteed to compare equal to 0 when using any
conforming implementation of C++, regardless of how null pointers are
represented. That's because NULL is required to expand into a null
pointer constant (21.2.3p2). 7.11p1 allows for only two possibilities
for a null pointer constant. The first is that it can be an "integer
literal with a value of zero", which obviously compares equal to 0. The
second is that it can be "a prvalue of type std::nullptr_t". Since the 0
it's being compared with also qualifies as a null pointer constant, they
necessarily compare equal (8.10p4). Therefore, checking whether NULL==0
doesn't give you any information about whether an implementation has
null pointers with all bits set to zero.
This matters if you've made the mistake of relying on things like
calloc() or memset(0) to fill pointer objects with representations of
null pointers. On the flip side, it's not a problem if you're relying
on zero-initialization, since zero-initialization of a pointer is
guaranteed to give it a valid representation of a null pointer(11.6p6,
7.11p1), even if that representation doesn't have all bits 0.

> Tests like
>
> if (!(array=calloc(hemeny,sizeof(arrayrcrd)))) // then deal with OOM.
>
> wouldn't work correctly otherwise.

Yes they will.
Clause 8.3.1p9 says "The operand of the logical negation operator ! is
contextually converted to bool (Clause 7); its value is true if the
converted operand is false and false otherwise. The type of the result
is bool." 7.14p1 describes the results of converting values to bool. It
says that "A ... null pointer value ... is converted to false ...".
That's true, regardless of how null pointers are represented. Therefore,
this code does precisely what it's supposed to do, regardless of that
representation.

Note that this also applies to if(array). In all statements that contain
a condition (other than switch), the condition is "... contextually
converted to bool ..." (9p4). All null pointers, regardless of how they
are represented, convert to a bool value of false, so using a pointer as
a condition always handles null pointer values the way you'd expect,
even if the representation of null values is not what you'd expect

Keith Thompson

unread,
Dec 31, 2019, 2:11:27 PM12/31/19
to
Chris Vine <chris@cvine--nospam--.freeserve.co.uk> writes:
[...]
> You have a point so far as concerns, say, memset'ing structs of
> trivial type to all-bits-zero where those structs contain pointers
> which you want to be NULL (should your code actually do that). But you

null, not NULL.

> are completely wrong in your example above. 'array' will be a null
> pointer constant if calloc fails, and the test for falsity will work
> correctly irrespective of whether the null pointer constant is
> signalled by all-bits-zero.

'array' will be a null pointer, not a null pointer constant.

A *null pointer constant* is a source code construct (and NULL is a
macro that expands to a null pointer constant). A *null pointer* is a
value that can exist at run time.

It's probably OK in most cases to use the term "NULL" to refer to a null
pointer value, but in this case the distinction is a large part of what
we're talking about, so I suggest being a bit more pedantic than usual.

> You have something wrong with your mental image of this.

Keith Thompson

unread,
Dec 31, 2019, 2:20:56 PM12/31/19
to
David Brown <david...@hesbynett.no> writes:
[...]
> It might compile - "NULL" can be defined as "#define NULL 0" rather
> than, say, "((void*) 0)".
>
> It is not in any way dependent on the representation of null pointers,
> as you probably know.

In C, NULL can be defined as 0 or as ((void*)0). In C++, ((void*)0) is
not a valid definition of NULL, because C++'s definition of "null
pointer constant" is more strict than C's.

A *null pointer constant* is an integer literal with value zero
or a prvalue of type std::nullptr_t. A null pointer constant
can be converted to a pointer type; the result is the *null
pointer value* of that type and is distinguishable from every
other value of object pointer or function pointer type.

(In C++11 and earlier, a integral constant expression with value
0 could be a null pointer constant, but C++14 restricted this to
integer literals. ((void*)0) hasn't been a valid C++ null pointer
constant going back at least to C++98.)

But yes, NULL might be usable in a context that requires an integer
value depending on how the implementation defines it. Of course it
would be silly to depend on that.

Chris Vine

unread,
Dec 31, 2019, 2:48:06 PM12/31/19
to
On Tue, 31 Dec 2019 11:11:17 -0800
Keith Thompson <Keith.S.T...@gmail.com> wrote:
> Chris Vine <chris@cvine--nospam--.freeserve.co.uk> writes:
> [...]
> > You have a point so far as concerns, say, memset'ing structs of
> > trivial type to all-bits-zero where those structs contain pointers
> > which you want to be NULL (should your code actually do that). But you
>
> null, not NULL.

I think you mean that "hold a null pointer value" should replace "be
NULL". If so, I don't object although I think the meaning is clear
enough and you are being somewhat on the pedantic side.

> > are completely wrong in your example above. 'array' will be a null
> > pointer constant if calloc fails, and the test for falsity will work
> > correctly irrespective of whether the null pointer constant is
> > signalled by all-bits-zero.
>
> 'array' will be a null pointer, not a null pointer constant.
>
> A *null pointer constant* is a source code construct (and NULL is a
> macro that expands to a null pointer constant). A *null pointer* is a
> value that can exist at run time.

I agree, clumsy language - for one thing, 'array' is neither a
constant nor a literal. As you say, I meant that 'array' will hold a
null pointer value. I doubt anyone misunderstood me however.

Jorgen Grahn

unread,
Dec 31, 2019, 4:37:45 PM12/31/19
to
On Tue, 2019-12-31, Ned Latham wrote:
> Melzzzzz wrote:
>> Ned Latham wrote:
>> > Öö Tiib wrote:
>
> ----snip----
>
>> > > You were asked example of it ... is it so hard to produce one?
>> >
>> > int i, j;
>> >
>> > if (i - j == NULL) // then do whatever.
>>
>> except that this does not compiles. Imlicit conversion of int to pointer
>> is not done...
>
> Ok. if ((void*)(i - j) == NULL) // then do whatever.

Then rewrite it as

if (i==j)

and that reason to know extra things about null pointers disappears.

/Jorgen

--
// Jorgen Grahn <grahn@ Oo o. . .
\X/ snipabacken.se> O o .

Jorgen Grahn

unread,
Dec 31, 2019, 4:55:06 PM12/31/19
to
On Mon, 2019-12-30, Öö Tiib wrote:
> On Monday, 30 December 2019 08:47:01 UTC+2, Keith Thompson wrote:
>> Ned Latham <nedl...@woden.valhalla.oz> writes:
>> >
>> > http://www.users.on.net/~nedlatham/Software/mclib/Documents/sourcecode.html
>> >
>> > Check AVLC and ListC, also read
>> > http://www.users.on.net/~nedlatham/Software/mclib/Documents/mclists.html
>
> It is not simple to find apprentices for a master with such style.
>
>> Can you give a *succinct* example? I'm not going to spend the time it
>> would take to read that.
>
> I have seen lot of code that assumes that null pointer has all bits clear.
> Most typical case is that contents of some byte buffer is zeroed. Can be
> calloc, memset, resize of byte vector or default-initialized byte array. As
> next step it is assumed that (properly aligned) bytes in such buffer can
> be now treated as nullptr.
>
>> Of course you *can* write code that depends on the representation of a
>> null pointer, but there is rarely a good reason to do so.
>
> The usual reason is ignorance. Rare people know details of ABI of C++
> for one or other platform and next to no one has expertise in extent
> of allowable by standard freedoms in ABI. Literal 0 is required to be
> null pointer constant and incorrect assumption that null pointer constant
> is required to have all bits clear is therefore trivial to make.
>
> It is often not expensive to rewrite such places into conforming and it
> likely does not affect any performance but fixes of never-manifesting
> defects can be intricate to sell and last minute changes can cause
> actual defects (in non-trivial code on about 50% of cases IME). So
> in review I typically request unit tests and static asserts about
> platform-specific assumptions instead of rewrite.

Thanks -- a sane and useful posting in this thread, at last.
(Other postings have been sane, but not useful. Including mine.)

I'm going to stop reading now, so my last Usenet read of 2019 is a
good one.

James Kuyper

unread,
Dec 31, 2019, 6:21:14 PM12/31/19
to
Ned Latham wrote:
> Ok. if ((void*)(i - j) == NULL)
> // then do whatever.

Were you under the impression that the left hand side of that comparison was required to be a null pointer value when i==j? There is no such requirement. The requirement you're probably thinking is 7.11p1, but that only applies to integer literals with a value of zero. (i - j) is not an integer literal.

Note that even if it does result in a null pointer value, the behavior would still not depend upon representation of null pointer values. NULL is required to expand to a null pointer constant, and the comparison causes it to be converted to void*, resulting in a null pointer value. All null pointer values are required to compare equal, regardless of how they are represented.

In any event, what did you expect this line of code to do that couldn't be done more simply and portable by writing if(i == j)?

James Kuyper

unread,
Dec 31, 2019, 11:30:19 PM12/31/19
to
On 12/31/19 11:46 AM, Ned Latham wrote:
> �� Tiib wrote:
>> Ned Latham wrote:
...
>> [conv.bool]
>> "A zero value, null pointer value, or null member pointer value is
>> converted to false; any other value is converted to true."
>
> News to me. Might be because I'm a lazy reader or because my references
> are out of date: Kernigan and Ritchie for C (ANSI 2) and Stroustrup
> (Edition 3) for C++. Both 1990s.

Yes, those sources are thirty years out of date. bool didn't even exist
in K&R C, and if conditions were and are handled differently. In first
edition of K&R C, it says "The unary negation operator ! converts a
non-zero or true operand into 0, and a zero or false operand into l."
However, the second edition came out shortly before the C89 was
approved, and used wording closer to that of the soon-to-be approved
standard: "The operand of the ! operator must have arithmetic type or be
a pointer, and the result is 1 if the value of its operand compares
equal to 0, and 0 otherwise." (A.7.4.7). The key issue may is the phrase
"compares equal to". What happens when a pointer value is compared for
equality with 0? Comparison for equality is covered by A.7.10, and for
the special case where a pointer is "compared to a constant integral
expression with a value of 0", it cross-references A.6.6. That
paragraphs indicates that comparison operators are one way in which an
integral constant expression with a value of 0 gets converted to pointer
type, and it specifies that "This produces a null pointer that is equal
to another null pointer of the same type, but unequal to any pointer to
a function or object."

Thus, !array has the value !(array==0), and array==0 has a value of true
if array is a null pointer, and 1 if it does not, completely independent
of how null pointers are represented.
That is exactly the way the same issue is handled in all later versions
of the C standard.

My copy of Stroustrup disappeared a long time ago. My copy of the C++98
standard was saved on a hard disk which crashed. The oldest version of
the standard I can locate is C++2011. As of that version, the relevant
issues were addressed in the same fashion as in the current version: the
unary ! is described in terms of inverting the result of a conversion to
bool, and the rules for conversion to bool specify that null pointer
values get converted to false. Thus, the result is guaranteed to be
false for null pointer values, regardless of how they are represented.

I'm curious: how does the description of these issues in your copy of
Stroustrup differ from those descriptions? With the preceding C standard
and the following C++ standards so carefully written to produce results
that are independent of how null pointers are represented, it would seem
very odd if that version of C++ was defined in a way which did depend
upon the representation.


>> It does not say that bit-wise checks are made,
>
> If NULL == 0, bitwise checks aren't required, just a check of the
> Z flag of the register that received the return.

How would that work? If null pointer values are, for instance,
represented by having all bits set to 1 (as has actually been done by at
least one implementation), NULL == 0 will still be true - the standard
requires it to be.

I suspect that your comments are specific to a particular architecture,
one for which "all bits 1" would not be a suitable choice for null
pointers. It was a very natural choice on the platform where that
representation was actually used.

David Brown

unread,
Jan 1, 2020, 11:01:54 AM1/1/20
to
On 31/12/2019 20:20, Keith Thompson wrote:
> David Brown <david...@hesbynett.no> writes:
> [...]
>> It might compile - "NULL" can be defined as "#define NULL 0" rather
>> than, say, "((void*) 0)".
>>
>> It is not in any way dependent on the representation of null pointers,
>> as you probably know.
>
> In C, NULL can be defined as 0 or as ((void*)0). In C++, ((void*)0) is
> not a valid definition of NULL, because C++'s definition of "null
> pointer constant" is more strict than C's.

True. My point was just an example of how NULL could be defined so that
the code that Melzzzzz thought would not compile, could be valid.

>
> A *null pointer constant* is an integer literal with value zero
> or a prvalue of type std::nullptr_t. A null pointer constant
> can be converted to a pointer type; the result is the *null
> pointer value* of that type and is distinguishable from every
> other value of object pointer or function pointer type.
>
> (In C++11 and earlier, a integral constant expression with value
> 0 could be a null pointer constant, but C++14 restricted this to
> integer literals. ((void*)0) hasn't been a valid C++ null pointer
> constant going back at least to C++98.)

Yes. In C, "((void*) 0)" is a common definition for NULL because it is
more expressive and restrictive in its valid uses than 0. In C++,
"nullptr" is typically used now, with "0" being the only (AFAIK)
portable definition that is valid in many C and C++ standards.

Particular compilers can, of course, have their own definitions. Many
gcc installations define it as __null.

>
> But yes, NULL might be usable in a context that requires an integer
> value depending on how the implementation defines it. Of course it
> would be silly to depend on that.
>

Agreed.

Manfred

unread,
Jan 1, 2020, 12:10:23 PM1/1/20
to
On 1/1/2020 5:30 AM, James Kuyper wrote:
> I'm curious: how does the description of these issues in your copy of
> Stroustrup differ from those descriptions? With the preceding C standard
> and the following C++ standards so carefully written to produce results
> that are independent of how null pointers are represented, it would seem
> very odd if that version of C++ was defined in a way which did depend
> upon the representation.

FWIW, the current (fourth) edition says (§7.2.2):
"Before nullptr was introduced, zero (0) was used as a notation for the
null pointer.
...
No object is allocated with the address 0, and 0 (the all-zeros bit
pattern) is the most common representation of nullptr. Zero (0) is an
int. However, the standard conversions (§10.5.2.3) allow 0 to be used as
a constant of pointer or pointer-to-member type."

AFAICT, other references to nullptr do not make assumptions on the
representation of the null pointer.

Note that §10.5.2.3 says that "A constant expression (...) that
evaluates to 0 can be implicitly converted to a null pointer of any
pointer type." and an example is given:

int* p = (1+2)*(2*(1-1)); // OK, but weird

"Prefer nullptr (§7.2.2)."

So, implicit conversion is not restricted to the integer literal 0
(although anything else than nullptr is in fact deprecated).

James Kuyper

unread,
Jan 1, 2020, 12:21:49 PM1/1/20
to
On 1/1/20 12:10 PM, Manfred wrote:
> On 1/1/2020 5:30 AM, James Kuyper wrote:
>> I'm curious: how does the description of these issues in your copy of
>> Stroustrup differ from those descriptions? With the preceding C standard
>> and the following C++ standards so carefully written to produce results
>> that are independent of how null pointers are represented, it would seem
>> very odd if that version of C++ was defined in a way which did depend
>> upon the representation.
>
> FWIW, the current (fourth) edition says (§7.2.2):
> "Before nullptr was introduced, zero (0) was used as a notation for the
> null pointer.
> ...
> No object is allocated with the address 0, and 0 (the all-zeros bit
> pattern) is the most common representation of nullptr. Zero (0) is an
> int. However, the standard conversions (§10.5.2.3) allow 0 to be used as
> a constant of pointer or pointer-to-member type."

That's not the most important issue. What does it say about:
1. Unary ! as applied to pointer values.
2. Conversion of pointer values to bool.
3. How if-conditions are interpreted.

> AFAICT, other references to nullptr do not make assumptions on the
> representation of the null pointer.
>
> Note that §10.5.2.3 says that "A constant expression (...) that
> evaluates to 0 can be implicitly converted to a null pointer of any
> pointer type." and an example is given:
>
> int* p = (1+2)*(2*(1-1)); // OK, but weird
>
> "Prefer nullptr (§7.2.2)."
>
> So, implicit conversion is not restricted to the integer literal 0
> (although anything else than nullptr is in fact deprecated).

Yes, that's a fairly recent change in the C++ standard - it used to
allow any integer constant expression with a value of 0, just like C
(though the C++ standard's definition of integral constant expressions
was slightly different from C's definition of integer constant expressions).

Of course, (i-j), where i and j are variables that just happen to
currently be equal, has never qualified, under any version of either
standard.

Tim Rentsch

unread,
Jan 10, 2020, 11:56:46 PM1/10/20
to
James Kuyper <james...@alumni.caltech.edu> writes:

> On 12/27/19 4:36 PM, Ian Collins wrote:
>
>> On 28/12/2019 10:24, T wrote:
>>
>>> Hi All,
>>>
>>> In C++, when you make a call to Windows Kernel32.dll
>>> and it wants a NULL for one or more of its parameters,
>>> what exactly is the structure of a NULL? A 32 bit
>>> word full of zeros?
>>
>> The C standard defines a null pointer as
>>
>> "An integer constant expression with the value 0, or such an expression
>> cast to type void *, is called a null pointer constant."
>
> That's the definition of a "null pointer constant". The definition of a
> null pointer comes on the immediately following line:
>
> "If a null pointer constant is converted to a pointer type, the
> resulting pointer, called a _null pointer_, is guaranteed to compare
> unequal to a pointer to any object or function."
> Note that the second occurrence of the phrase "null pointer" in that
> sentence is in italics, an ISO convention indicating that this sentence
> constitutes the official definition of the italicized phrase. In this
> case, it's a little unclear; the first part of that sentence is not
> actually the definition, it's a one of several ways to obtain a null
> pointer (other ways include calling various standard library functions
> that are documented as returning null pointers under certain
> circumstances). It's actually the end of that sentence that defines what
> null pointer is: a pointer guaranteed to compare unequal to a pointer to
> any object or function.

The first part of the sentence is the definition. Other ways of
obtaining a null pointer value therefore must have derived that
value, at some point in the program's history, by converting a
null pointer to some pointer type. The second part of the
sentence gives a property that null pointers must satisfy, but is
not the definition of null pointer. It is perfectly possible to
have a pointer value that compares unequal to a pointer to any
object or function, but is not a null pointer.
0 new messages