Discussion:
question about nullptr
(too old to reply)
Thiago Adams
2024-07-06 11:49:04 UTC
Permalink
If you were creating C code today and could use a C23 compiler, would
you use nullptr instead of NULL?

I am asking because I think I will keep using NULL.

I like nullptr semantics but I don't like to introduce new element
(nullptr) inside the code with no guarantee that the code will not mix both.

In the past we also didn't have a guarantee we are not mixing 0 or NULL.

I think the best scenario for a team guideline would be a style warning
if 0 or nullptr is used and NULL to be defined as nullptr in a C23 compiler.
Bonita Montero
2024-07-06 12:13:26 UTC
Permalink
Post by Thiago Adams
If you were creating C code today and could use a C23 compiler, would
you use nullptr instead of NULL?
I am asking because I think I will keep using NULL.
I like nullptr semantics but I don't like to introduce new element
(nullptr) inside the code with no guarantee that the code will not mix both.
In the past we also didn't have a guarantee we are not mixing 0 or NULL.
I think the best scenario for a team guideline would be a style warning
if 0 or nullptr is used and NULL to be defined as nullptr in a C23 compiler.
I don't know what nullptr is good for in C23. In C++ it makes sense
to have a nullptr to distinguish overloads that take a pointer and
those that take an integral; but in C there ain't overloads.
John McCue
2024-07-06 12:33:11 UTC
Permalink
Post by Thiago Adams
If you were creating C code today and could use a C23 compiler, would
you use nullptr instead of NULL?
I avoid the use of new c items because I want full
portability. Some systems may have older compilers.
Post by Thiago Adams
I am asking because I think I will keep using NULL.
I will do the same

<snip>
--
[t]csh(1) - "An elegant shell, for a more... civilized age."
- Paraphrasing Star Wars
Kaz Kylheku
2024-07-06 12:54:26 UTC
Permalink
Post by Thiago Adams
If you were creating C code today and could use a C23 compiler, would
you use nullptr instead of NULL?
In greenfield projects under my dictatorship, I use 0, as in:

char *p = 0;

I was still 20 something when I (easily) wrapped my head around the 0
null pointer constant, and have not had any problems with it.
Once I learned the standard-defined truth about null pointer constants,
and their relationship to the NULL macro, I dropped NULL like a hot
potato, and didn't look back (except when working in code bases that use
NULL).
--
TXR Programming Language: http://nongnu.org/txr
Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal
Mastodon: @***@mstdn.ca
Janis Papanagnou
2024-07-06 13:07:11 UTC
Permalink
Post by Kaz Kylheku
Post by Thiago Adams
If you were creating C code today and could use a C23 compiler, would
you use nullptr instead of NULL?
char *p = 0;
I was still 20 something when I (easily) wrapped my head around the 0
null pointer constant, and have not had any problems with it.
Once I learned the standard-defined truth about null pointer constants,
and their relationship to the NULL macro, I dropped NULL like a hot
potato, and didn't look back (except when working in code bases that use
NULL).
We also used 0 as "universal" pointer value regularly without problems.

One practical advantage of adding a named entity (with a value of 0)
was to easily grep (find) appearances of this value in source code.

Janis
Scott Lurndal
2024-07-06 14:04:01 UTC
Permalink
Post by Janis Papanagnou
Post by Kaz Kylheku
Post by Thiago Adams
If you were creating C code today and could use a C23 compiler, would
you use nullptr instead of NULL?
char *p = 0;
I was still 20 something when I (easily) wrapped my head around the 0
null pointer constant, and have not had any problems with it.
Once I learned the standard-defined truth about null pointer constants,
and their relationship to the NULL macro, I dropped NULL like a hot
potato, and didn't look back (except when working in code bases that use
NULL).
We also used 0 as "universal" pointer value regularly without problems.
Whereas I spent 6 years programming on an architecture[*] where a
null pointer was represented in hardware by the value 0xc0eeeeee. I always
use the NULL macro in both C and C++ code.

[*] now obsolete.
Janis Papanagnou
2024-07-06 14:42:05 UTC
Permalink
Post by Scott Lurndal
Post by Janis Papanagnou
We also used 0 as "universal" pointer value regularly without problems.
Whereas I spent 6 years programming on an architecture[*] where a
null pointer was represented in hardware by the value 0xc0eeeeee.
Yes, but a 0 pointer value has not the meaning of an int value 0.

Janis
Post by Scott Lurndal
I always
use the NULL macro in both C and C++ code.
[*] now obsolete.
Janis Papanagnou
2024-07-06 14:45:14 UTC
Permalink
Post by Janis Papanagnou
Post by Scott Lurndal
Post by Janis Papanagnou
We also used 0 as "universal" pointer value regularly without problems.
Whereas I spent 6 years programming on an architecture[*] where a
null pointer was represented in hardware by the value 0xc0eeeeee.
Yes, but a 0 pointer value has not the meaning of an int value 0.
(Probably badly worded.)

I meant; the internal binary representation of a 0 pointer value
has not necessarily the internal binary representation of an int
value 0. (So you could use it also in architectures like the one
you mention.)

Janis
Post by Janis Papanagnou
Post by Scott Lurndal
I always
use the NULL macro in both C and C++ code.
[*] now obsolete.
Andrey Tarasevich
2024-07-06 17:50:22 UTC
Permalink
Post by Scott Lurndal
Whereas I spent 6 years programming on an architecture[*] where a
null pointer was represented in hardware by the value 0xc0eeeeee. I always
use the NULL macro in both C and C++ code.
But that achieved absolutely nothing over using plain `0` in the source
code.

The `NULL` you used was still defined as `0` (in C++ libs) and 0 or
`(void *) 0` (in C libs).
--
Best regards,
Andrey
Scott Lurndal
2024-07-06 23:04:19 UTC
Permalink
Post by Andrey Tarasevich
Post by Scott Lurndal
Whereas I spent 6 years programming on an architecture[*] where a
null pointer was represented in hardware by the value 0xc0eeeeee. I always
use the NULL macro in both C and C++ code.
But that achieved absolutely nothing over using plain `0` in the source
code.
The `NULL` you used was still defined as `0` (in C++ libs) and 0 or
`(void *) 0` (in C libs).
Which ambiguity is yet another reason to use the NULL or nullptr
tokens.
Tim Rentsch
2024-07-07 03:06:49 UTC
Permalink
Post by Scott Lurndal
Post by Andrey Tarasevich
Post by Scott Lurndal
Whereas I spent 6 years programming on an architecture[*] where a
null pointer was represented in hardware by the value 0xc0eeeeee. I always
use the NULL macro in both C and C++ code.
But that achieved absolutely nothing over using plain `0` in the source
code.
The `NULL` you used was still defined as `0` (in C++ libs) and 0 or
`(void *) 0` (in C libs).
Which ambiguity is yet another reason to use the NULL or nullptr
tokens.
The definition of NULL is ambiguous and that is a reason in
/favor/ of using NULL? Not to me it isn't.
bart
2024-07-06 18:20:15 UTC
Permalink
Post by Scott Lurndal
Post by Janis Papanagnou
Post by Kaz Kylheku
Post by Thiago Adams
If you were creating C code today and could use a C23 compiler, would
you use nullptr instead of NULL?
char *p = 0;
I was still 20 something when I (easily) wrapped my head around the 0
null pointer constant, and have not had any problems with it.
Once I learned the standard-defined truth about null pointer constants,
and their relationship to the NULL macro, I dropped NULL like a hot
potato, and didn't look back (except when working in code bases that use
NULL).
We also used 0 as "universal" pointer value regularly without problems.
Whereas I spent 6 years programming on an architecture[*] where a
null pointer was represented in hardware by the value 0xc0eeeeee. I always
use the NULL macro in both C and C++ code.
You can ignore that requirement and just use all-bits-zero (in memory,
not just in C source code). After all, the only thing you might want
hardware support for is trapping a dereference of a NULL value.

Presumably it was more of an ABI thing where all languages/compilers
complying with it had to use the same NULL value, so the choice could
have been made there.
Scott Lurndal
2024-07-06 23:09:24 UTC
Permalink
Post by bart
Post by Scott Lurndal
Post by Janis Papanagnou
Post by Kaz Kylheku
Post by Thiago Adams
If you were creating C code today and could use a C23 compiler, would
you use nullptr instead of NULL?
char *p = 0;
I was still 20 something when I (easily) wrapped my head around the 0
null pointer constant, and have not had any problems with it.
Once I learned the standard-defined truth about null pointer constants,
and their relationship to the NULL macro, I dropped NULL like a hot
potato, and didn't look back (except when working in code bases that use
NULL).
We also used 0 as "universal" pointer value regularly without problems.
Whereas I spent 6 years programming on an architecture[*] where a
null pointer was represented in hardware by the value 0xc0eeeeee. I always
use the NULL macro in both C and C++ code.
You can ignore that requirement and just use all-bits-zero (in memory,
not just in C source code). After all, the only thing you might want
hardware support for is trapping a dereference of a NULL value.
Actually, that is incorrect.

The hardware supported an instruction to search a linked list
for a specified key (up to 100 units[*] in length). The search
instruction specified the head of list pointer, offset to next
link field and a condition
(<, <=, ==, !=, >=, >, any-bit-equal, no-bit-equal, max) and
would search the specified list until the condition was met
or the null pointer was read. The instruction returned the
target node or the null pointer in an output register.

[*] 1-to-100 bytes or 1-to-100 BCD digits.
Keith Thompson
2024-07-06 23:31:44 UTC
Permalink
[...]
Post by bart
Post by Scott Lurndal
Whereas I spent 6 years programming on an architecture[*] where a
null pointer was represented in hardware by the value 0xc0eeeeee. I always
use the NULL macro in both C and C++ code.
You can ignore that requirement and just use all-bits-zero (in memory,
not just in C source code). After all, the only thing you might want
hardware support for is trapping a dereference of a NULL value.
You write this in response to someone saying they've used a system
where a null pointer is *not* all-bits-zero.

The vast majority of systems do represent a null pointer as
all-bits-zero, and you can usually get away with assuming that.
There are even some cases where it might be worthwhile, for example
if you need to memset chunks of memory that contain pointers and
aren't concerned about 100% portability (or if you're using your
own langauge).

Or you can use the language in a way that works correctly regardless
of now null pointers are represented. That's what I do.

[...]
--
Keith Thompson (The_Other_Keith) Keith.S.Thompson+***@gmail.com
void Void(void) { Void(); } /* The recursive call of the void */
Chris M. Thomasson
2024-07-06 20:23:30 UTC
Permalink
Post by Scott Lurndal
Post by Janis Papanagnou
Post by Kaz Kylheku
Post by Thiago Adams
If you were creating C code today and could use a C23 compiler, would
you use nullptr instead of NULL?
char *p = 0;
I was still 20 something when I (easily) wrapped my head around the 0
null pointer constant, and have not had any problems with it.
Once I learned the standard-defined truth about null pointer constants,
and their relationship to the NULL macro, I dropped NULL like a hot
potato, and didn't look back (except when working in code bases that use
NULL).
We also used 0 as "universal" pointer value regularly without problems.
Whereas I spent 6 years programming on an architecture[*] where a
null pointer was represented in hardware by the value 0xc0eeeeee. I always
use the NULL macro in both C and C++ code.
Where:

void* x = 0;

Should be x = 0xc0eeeeee, right?
Chris M. Thomasson
2024-07-06 20:28:21 UTC
Permalink
Post by Chris M. Thomasson
Post by Scott Lurndal
Post by Janis Papanagnou
Post by Thiago Adams
If you were creating C code today and could use a C23 compiler, would
you use nullptr instead of NULL?
    char *p = 0;
I was still 20 something when I (easily) wrapped my head around the 0
null pointer constant, and have not had any problems with it.
Once I learned the standard-defined truth about null pointer constants,
and their relationship to the NULL macro, I dropped NULL like a hot
potato, and didn't look back (except when working in code bases that use
NULL).
We also used 0 as "universal" pointer value regularly without problems.
Whereas I spent 6 years programming on an architecture[*] where a
null pointer was represented in hardware by the value 0xc0eeeeee.  I
always
use the NULL macro in both C and C++ code.
void* x = 0;
Should be x = 0xc0eeeeee, right?
void* a = 0;
void* b = NULL;

a == b, right?
Lawrence D'Oliveiro
2024-07-07 08:01:48 UTC
Permalink
Post by Chris M. Thomasson
void* a = 0;
void* b = NULL;
a == b, right?
According to the C spec, yes.
Chris M. Thomasson
2024-07-09 05:08:56 UTC
Permalink
Post by Lawrence D'Oliveiro
Post by Chris M. Thomasson
void* a = 0;
void* b = NULL;
a == b, right?
According to the C spec, yes.
Indeed. :^)
Richard Damon
2024-07-06 21:04:59 UTC
Permalink
Post by Chris M. Thomasson
Post by Scott Lurndal
Post by Janis Papanagnou
Post by Thiago Adams
If you were creating C code today and could use a C23 compiler, would
you use nullptr instead of NULL?
    char *p = 0;
I was still 20 something when I (easily) wrapped my head around the 0
null pointer constant, and have not had any problems with it.
Once I learned the standard-defined truth about null pointer constants,
and their relationship to the NULL macro, I dropped NULL like a hot
potato, and didn't look back (except when working in code bases that use
NULL).
We also used 0 as "universal" pointer value regularly without problems.
Whereas I spent 6 years programming on an architecture[*] where a
null pointer was represented in hardware by the value 0xc0eeeeee.  I
always
use the NULL macro in both C and C++ code.
void* x = 0;
Should be x = 0xc0eeeeee, right?
Maybe when the representation of x is examined by reinterpreting it as
an array of character types (like unsigned char).
Scott Lurndal
2024-07-06 23:10:42 UTC
Permalink
Post by Richard Damon
Post by Chris M. Thomasson
Post by Scott Lurndal
Post by Janis Papanagnou
Post by Thiago Adams
If you were creating C code today and could use a C23 compiler, would
you use nullptr instead of NULL?
    char *p = 0;
I was still 20 something when I (easily) wrapped my head around the 0
null pointer constant, and have not had any problems with it.
Once I learned the standard-defined truth about null pointer constants,
and their relationship to the NULL macro, I dropped NULL like a hot
potato, and didn't look back (except when working in code bases that use
NULL).
We also used 0 as "universal" pointer value regularly without problems.
Whereas I spent 6 years programming on an architecture[*] where a
null pointer was represented in hardware by the value 0xc0eeeeee.  I
always
use the NULL macro in both C and C++ code.
void* x = 0;
Should be x = 0xc0eeeeee, right?
Maybe when the representation of x is examined by reinterpreting it as
an array of character types (like unsigned char).
FWIW, this was on a BCD architecture. Pointers were an 32-bit (8 digit)
field with a sign digit, base-selection digit and six-digit offset.
Scott Lurndal
2024-07-06 23:03:38 UTC
Permalink
Post by Chris M. Thomasson
Post by Scott Lurndal
Post by Janis Papanagnou
Post by Kaz Kylheku
Post by Thiago Adams
If you were creating C code today and could use a C23 compiler, would
you use nullptr instead of NULL?
char *p = 0;
I was still 20 something when I (easily) wrapped my head around the 0
null pointer constant, and have not had any problems with it.
Once I learned the standard-defined truth about null pointer constants,
and their relationship to the NULL macro, I dropped NULL like a hot
potato, and didn't look back (except when working in code bases that use
NULL).
We also used 0 as "universal" pointer value regularly without problems.
Whereas I spent 6 years programming on an architecture[*] where a
null pointer was represented in hardware by the value 0xc0eeeeee. I always
use the NULL macro in both C and C++ code.
void* x = 0;
Should be x = 0xc0eeeeee, right?
Sort of. In the context of the processor only the
low-order 24-bits (6 BCD digits) indicated the null
pointer. '0xc' was a positive sign and the following
digit selected one of eight base-limit registers.
James Kuyper
2024-07-07 01:44:03 UTC
Permalink
...
Post by Chris M. Thomasson
Post by Scott Lurndal
Whereas I spent 6 years programming on an architecture[*] where a
null pointer was represented in hardware by the value 0xc0eeeeee.  I
always
use the NULL macro in both C and C++ code.
void* x = 0;
Should be x = 0xc0eeeeee, right?
No, 0 is a null pointer constant. The C standard requires that when a
null pointer constant is converted to a pointer value, it must be
converted to a null pointer of that type. The result will be that the
representation of 'x' after such an assignment would be 0xc0eeeeee.

Whether or not an integer value of 0xc0eeeeee can be converted to a
pointer type, and what that pointer's value would be after the
conversion is up to the implementation.

Note that even after x acquires that representation, it's still required
to compare equal to 0. For the purposes of the comparison, the null
pointer constant gets converted to a null pointer of the appropriate
type. All null pointers, regardless of representation (the C standard
allows there to be multiple ways of representing null pointers) must
compare equal.
Keith Thompson
2024-07-07 02:29:20 UTC
Permalink
Post by James Kuyper
...
Post by Chris M. Thomasson
Post by Scott Lurndal
Whereas I spent 6 years programming on an architecture[*] where a
null pointer was represented in hardware by the value 0xc0eeeeee.  I
always
use the NULL macro in both C and C++ code.
void* x = 0;
Should be x = 0xc0eeeeee, right?
No, 0 is a null pointer constant. The C standard requires that when a
null pointer constant is converted to a pointer value, it must be
converted to a null pointer of that type. The result will be that the
representation of 'x' after such an assignment would be 0xc0eeeeee.
Whether or not an integer value of 0xc0eeeeee can be converted to a
pointer type, and what that pointer's value would be after the
conversion is up to the implementation.
Note that even after x acquires that representation, it's still required
to compare equal to 0. For the purposes of the comparison, the null
pointer constant gets converted to a null pointer of the appropriate
type. All null pointers, regardless of representation (the C standard
allows there to be multiple ways of representing null pointers) must
compare equal.
Furthermore, `void* x = 0xc0eeeeee;` is a constraint violation. There
is no implicit conversion from integers to pointers other than the
special case of a null pointer constant, which 0xc0eeeeee is not.
--
Keith Thompson (The_Other_Keith) Keith.S.Thompson+***@gmail.com
void Void(void) { Void(); } /* The recursive call of the void */
Chris M. Thomasson
2024-07-07 19:53:17 UTC
Permalink
Post by Keith Thompson
Post by James Kuyper
...
Post by Chris M. Thomasson
Post by Scott Lurndal
Whereas I spent 6 years programming on an architecture[*] where a
null pointer was represented in hardware by the value 0xc0eeeeee.  I
always
use the NULL macro in both C and C++ code.
void* x = 0;
Should be x = 0xc0eeeeee, right?
No, 0 is a null pointer constant. The C standard requires that when a
null pointer constant is converted to a pointer value, it must be
converted to a null pointer of that type. The result will be that the
representation of 'x' after such an assignment would be 0xc0eeeeee.
Whether or not an integer value of 0xc0eeeeee can be converted to a
pointer type, and what that pointer's value would be after the
conversion is up to the implementation.
Note that even after x acquires that representation, it's still required
to compare equal to 0. For the purposes of the comparison, the null
pointer constant gets converted to a null pointer of the appropriate
type. All null pointers, regardless of representation (the C standard
allows there to be multiple ways of representing null pointers) must
compare equal.
Furthermore, `void* x = 0xc0eeeeee;` is a constraint violation. There
is no implicit conversion from integers to pointers other than the
special case of a null pointer constant, which 0xc0eeeeee is not.
void* x = (void*)(0xc0eeeeee); // aka NULL
void* y = 0; // NULL, right?

x == y is true...

Still shitty?
Lawrence D'Oliveiro
2024-07-07 08:03:09 UTC
Permalink
Post by Chris M. Thomasson
void* x = 0;
Should be x = 0xc0eeeeee, right?
Only in the sense of doing an unsafe conversion, like via a union type,
for example.
Ben Bacarisse
2024-07-06 22:14:40 UTC
Permalink
Post by Scott Lurndal
Post by Janis Papanagnou
Post by Kaz Kylheku
Post by Thiago Adams
If you were creating C code today and could use a C23 compiler, would
you use nullptr instead of NULL?
char *p = 0;
I was still 20 something when I (easily) wrapped my head around the 0
null pointer constant, and have not had any problems with it.
Once I learned the standard-defined truth about null pointer constants,
and their relationship to the NULL macro, I dropped NULL like a hot
potato, and didn't look back (except when working in code bases that use
NULL).
We also used 0 as "universal" pointer value regularly without
problems.
I also like to use 0, but I'm not sure I could say exactly why. Maybe
because of pre-C exposure (B and BCPL).
Post by Scott Lurndal
Whereas I spent 6 years programming on an architecture[*] where a
null pointer was represented in hardware by the value 0xc0eeeeee. I always
use the NULL macro in both C and C++ code.
I'm sure you know (but maybe some other readers might not) that that
does not stop one using 0 in C source code. Whatever a null pointer
"really" is on some hardware, 0 must work in C, including in comparisons
with == and !=. You can have

void *ptr = 0;
if (ptr == 0) ...

being true and also

memcmp(&ptr,
&(union { unsigned int u; void *p; }){ .u=0xc0eeeeee }.p,
sizeof ptr) == 0

being true.
Post by Scott Lurndal
[*] now obsolete.
--
Ben.
Scott Lurndal
2024-07-06 23:13:02 UTC
Permalink
Post by Ben Bacarisse
Post by Scott Lurndal
Post by Janis Papanagnou
Post by Kaz Kylheku
Post by Thiago Adams
If you were creating C code today and could use a C23 compiler, would
you use nullptr instead of NULL?
char *p = 0;
I was still 20 something when I (easily) wrapped my head around the 0
null pointer constant, and have not had any problems with it.
Once I learned the standard-defined truth about null pointer constants,
and their relationship to the NULL macro, I dropped NULL like a hot
potato, and didn't look back (except when working in code bases that use
NULL).
We also used 0 as "universal" pointer value regularly without
problems.
I also like to use 0, but I'm not sure I could say exactly why. Maybe
because of pre-C exposure (B and BCPL).
Post by Scott Lurndal
Whereas I spent 6 years programming on an architecture[*] where a
null pointer was represented in hardware by the value 0xc0eeeeee. I always
use the NULL macro in both C and C++ code.
I'm sure you know (but maybe some other readers might not) that that
does not stop one using 0 in C source code. Whatever a null pointer
"really" is on some hardware, 0 must work in C, including in comparisons
with == and !=. You can have
Yes. However, I consider that ambiguous, I prefer to be explicit and
use NULL or nullptr. Horses for courses.
Tim Rentsch
2024-07-07 03:10:50 UTC
Permalink
Post by Ben Bacarisse
Post by Scott Lurndal
Post by Janis Papanagnou
Post by Kaz Kylheku
Post by Thiago Adams
If you were creating C code today and could use a C23 compiler, would
you use nullptr instead of NULL?
char *p = 0;
I was still 20 something when I (easily) wrapped my head around the 0
null pointer constant, and have not had any problems with it.
Once I learned the standard-defined truth about null pointer constants,
and their relationship to the NULL macro, I dropped NULL like a hot
potato, and didn't look back (except when working in code bases that use
NULL).
We also used 0 as "universal" pointer value regularly without problems.
I also like to use 0, but I'm not sure I could say exactly why. Maybe
because of pre-C exposure (B and BCPL).
Post by Scott Lurndal
Whereas I spent 6 years programming on an architecture[*] where a
null pointer was represented in hardware by the value 0xc0eeeeee. I always
use the NULL macro in both C and C++ code.
I'm sure you know (but maybe some other readers might not) that that
does not stop one using 0 in C source code. Whatever a null pointer
"really" is on some hardware, 0 must work in C, including in comparisons
with == and !=. You can have
Yes. However, I consider that ambiguous, [...]
You consider something that is not ambiguous to be ambiguous? You must
mean something different by the word ambiguous than I do.
Kaz Kylheku
2024-07-07 08:46:10 UTC
Permalink
Post by Scott Lurndal
Post by Ben Bacarisse
I'm sure you know (but maybe some other readers might not) that that
does not stop one using 0 in C source code. Whatever a null pointer
"really" is on some hardware, 0 must work in C, including in comparisons
with == and !=. You can have
Yes. However, I consider that ambiguous, I prefer to be explicit and
use NULL or nullptr. Horses for courses.
The thing is that "null" is a word that means "zero".

So it's a bit like saying

#define tri 3

is less ambiguous compared to just using 3.

I get it that 0 is not exclusively a pointer constant, and syntax alone
doesn't indicate which; indeed without type information, we don't know
whether p == 0 is a pointer comparison, floating-point comparison or
integer comparison. Whereas with some other kinds of expressions,
we know more: e.g. p->memb, if correct, tells us that p is a pointer
to a struct or union.

If we have to use someting other than 0 to help us understand p == 0,
maybe the circumstances of the p are not clear enough?

What about "if (p)" and "if (!p)". If 0 is ambiguous, these should
always be written "if (p != nullptr)" and "if (p == nullptr)".
Otherwise p could be a number.

(Indeed, there are coding conventions like that: always use NULL,
and do not test pointers as if they were Booleans.)
--
TXR Programming Language: http://nongnu.org/txr
Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal
Mastodon: @***@mstdn.ca
Ben Bacarisse
2024-07-07 18:59:25 UTC
Permalink
Post by Scott Lurndal
Post by Ben Bacarisse
Post by Scott Lurndal
Post by Janis Papanagnou
Post by Kaz Kylheku
Post by Thiago Adams
If you were creating C code today and could use a C23 compiler, would
you use nullptr instead of NULL?
char *p = 0;
I was still 20 something when I (easily) wrapped my head around the 0
null pointer constant, and have not had any problems with it.
Once I learned the standard-defined truth about null pointer constants,
and their relationship to the NULL macro, I dropped NULL like a hot
potato, and didn't look back (except when working in code bases that use
NULL).
We also used 0 as "universal" pointer value regularly without problems.
I also like to use 0, but I'm not sure I could say exactly why. Maybe
because of pre-C exposure (B and BCPL).
Post by Scott Lurndal
Whereas I spent 6 years programming on an architecture[*] where a
null pointer was represented in hardware by the value 0xc0eeeeee. I always
use the NULL macro in both C and C++ code.
I'm sure you know (but maybe some other readers might not) that that
does not stop one using 0 in C source code. Whatever a null pointer
"really" is on some hardware, 0 must work in C, including in comparisons
with == and !=. You can have
Yes. However, I consider that ambiguous, I prefer to be explicit and
use NULL or nullptr.
In what sense is using 0 ambiguous? I can't see it.

Ambiguous and explicit are not opposites, so many you did not mean to
say that 0 is ambiguous. Its use does require the reader to know the
role played by zero integer constant expressions in C.

But then NULL might be defined to be 0. It /looks/ more like a pointer
but there's lots of code that erroneously assumes that it is, presumably
because of that deceptive look. (nullptr is another matter.)

Do you always cast NULL to a pointer in those (admittedly rare) cases
when one needs to? I think it's easier to remember to do that with 0.
--
Ben.
Scott Lurndal
2024-07-07 19:40:53 UTC
Permalink
Post by Ben Bacarisse
Post by Scott Lurndal
Post by Ben Bacarisse
Post by Scott Lurndal
Post by Janis Papanagnou
Post by Kaz Kylheku
Post by Thiago Adams
If you were creating C code today and could use a C23 compiler, would
you use nullptr instead of NULL?
char *p = 0;
I was still 20 something when I (easily) wrapped my head around the 0
null pointer constant, and have not had any problems with it.
Once I learned the standard-defined truth about null pointer constants,
and their relationship to the NULL macro, I dropped NULL like a hot
potato, and didn't look back (except when working in code bases that use
NULL).
We also used 0 as "universal" pointer value regularly without problems.
I also like to use 0, but I'm not sure I could say exactly why. Maybe
because of pre-C exposure (B and BCPL).
Post by Scott Lurndal
Whereas I spent 6 years programming on an architecture[*] where a
null pointer was represented in hardware by the value 0xc0eeeeee. I always
use the NULL macro in both C and C++ code.
I'm sure you know (but maybe some other readers might not) that that
does not stop one using 0 in C source code. Whatever a null pointer
"really" is on some hardware, 0 must work in C, including in comparisons
with == and !=. You can have
Yes. However, I consider that ambiguous, I prefer to be explicit and
use NULL or nullptr.
In what sense is using 0 ambiguous? I can't see it.
the digit zero is context dependent, which makes it ambiguous.

I.e. it can either be a null pointer or the value zero
depending on context, which makes it ambiguous to the casual
reader. Particularly when reading code that someone
else has written. NULL makes the programmers intent crystal
clear.
Post by Ben Bacarisse
Do you always cast NULL to a pointer in those (admittedly rare) cases
when one needs to?
I may have back in the days when I was using Version 6 C and
AT&T C where

$ grep NULL /work/reference/usl/uw2.01/usr/src/common/head/stddef.h
#ifndef NULL
#define NULL 0


I use gcc today and it defines NULL for C as

#define NULL ((void *)0)
Keith Thompson
2024-07-07 22:17:34 UTC
Permalink
[...]
Post by Scott Lurndal
Post by Ben Bacarisse
Do you always cast NULL to a pointer in those (admittedly rare) cases
when one needs to?
I may have back in the days when I was using Version 6 C and
AT&T C where
$ grep NULL /work/reference/usl/uw2.01/usr/src/common/head/stddef.h
#ifndef NULL
#define NULL 0
I use gcc today and it defines NULL for C as
#define NULL ((void *)0)
Consider a variadic function that uses a null pointer to terminate the
argument list. Then I always use NULL cast to the appropriate pointer
type.

For example, execl() requires a final argument that should be
`(char*)NULL`.

On the other hand, execl() is specified by POSIX, which also happens to
require NULL to be of type void* -- and you can pretty much get away
with using a void* null pointer where a char* null pointer is expected.

But casting NULL to the appropriate type (checked by reading the man
page) requires less thought.

I just about always use NULL, not 0, when I want a null pointer
constant. Similarly, I use '\0', not 0, when I want a null character,
0.0 when I want a floating-point zero, and false when I want a Boolean
zero. I just like being explicit.

In C23, I'll use nullptr rather than NULL *if* I don't care about
portability to pre-C23 compilers. (I use nullptr in C++.)
--
Keith Thompson (The_Other_Keith) Keith.S.Thompson+***@gmail.com
void Void(void) { Void(); } /* The recursive call of the void */
Scott Lurndal
2024-07-08 14:09:35 UTC
Permalink
Post by Keith Thompson
[...]
Post by Scott Lurndal
Post by Ben Bacarisse
Do you always cast NULL to a pointer in those (admittedly rare) cases
when one needs to?
I may have back in the days when I was using Version 6 C and
AT&T C where
$ grep NULL /work/reference/usl/uw2.01/usr/src/common/head/stddef.h
#ifndef NULL
#define NULL 0
I use gcc today and it defines NULL for C as
#define NULL ((void *)0)
Consider a variadic function that uses a null pointer to terminate the
argument list. Then I always use NULL cast to the appropriate pointer
type.
For example, execl() requires a final argument that should be
`(char*)NULL`.
On the other hand, execl() is specified by POSIX, which also happens to
require NULL to be of type void* -- and you can pretty much get away
with using a void* null pointer where a char* null pointer is expected.
Yes, that would be my reading.
Post by Keith Thompson
But casting NULL to the appropriate type (checked by reading the man
page) requires less thought.
Perhaps. For me, it is more rote than thought at this point.

And it's been a couple of decades since I needed to call
one of the exec functions directly :-)
Post by Keith Thompson
I just about always use NULL, not 0, when I want a null pointer
constant. Similarly, I use '\0', not 0, when I want a null character,
0.0 when I want a floating-point zero, and false when I want a Boolean
zero. I just like being explicit.
I agree 100% with this.
Post by Keith Thompson
In C23, I'll use nullptr rather than NULL *if* I don't care about
portability to pre-C23 compilers. (I use nullptr in C++.)
I haven't made the transition to nullptr in C++ yet, too many years
of using NULL and code bases that need to compile with older
standards (pre C++11, until very recently) - granted one might

#define nullptr (void *)NULL
Keith Thompson
2024-07-08 20:32:38 UTC
Permalink
[...]
Post by Scott Lurndal
Post by Keith Thompson
In C23, I'll use nullptr rather than NULL *if* I don't care about
portability to pre-C23 compilers. (I use nullptr in C++.)
I haven't made the transition to nullptr in C++ yet, too many years
of using NULL and code bases that need to compile with older
standards (pre C++11, until very recently) - granted one might
#define nullptr (void *)NULL
I've thought about doing something like that, but I haven't had the
opportunity so far, and I'm not sure I would.

I might write something like:

#if __STDC_VERSION__ < 202311L
#define nullptr ((void*)NULL)
#endif

But if I had to compile with both pre-C23 and newer compilers, I'd be
more likely to just use NULL (with a cast where necessary). I'd
consider the `#define nullptr` trick if pre-C23 compilers were rare.
--
Keith Thompson (The_Other_Keith) Keith.S.Thompson+***@gmail.com
void Void(void) { Void(); } /* The recursive call of the void */
Janis Papanagnou
2024-07-08 18:11:13 UTC
Permalink
Post by Keith Thompson
I just about always use NULL, not 0, when I want a null pointer
constant. Similarly, I use '\0', not 0, when I want a null character,
0.0 when I want a floating-point zero, and false when I want a Boolean
zero. I just like being explicit.
Same here. Absolutely.

Janis
Michael S
2024-07-08 19:28:04 UTC
Permalink
On Sun, 07 Jul 2024 15:17:34 -0700
Post by Keith Thompson
I just about always use NULL, not 0, when I want a null pointer
constant. Similarly, I use '\0', not 0, when I want a null character,
0.0 when I want a floating-point zero, and false when I want a Boolean
zero. I just like being explicit.
Pointer: I very rarely use NULL.
Character: I never use '\0'.
Floating point: I never use 0.0.
Boolean: I use false much more often than 0.
Chris M. Thomasson
2024-07-08 22:23:47 UTC
Permalink
Post by Michael S
On Sun, 07 Jul 2024 15:17:34 -0700
Post by Keith Thompson
I just about always use NULL, not 0, when I want a null pointer
constant. Similarly, I use '\0', not 0, when I want a null character,
0.0 when I want a floating-point zero, and false when I want a Boolean
zero. I just like being explicit.
Pointer: I very rarely use NULL.
Character: I never use '\0'.
Not even something like:

#define CLINE 128

char x[CLINE] = { '\0' };

?

;^)
Post by Michael S
Floating point: I never use 0.0.
Boolean: I use false much more often than 0.
Michael S
2024-07-09 07:48:48 UTC
Permalink
On Mon, 8 Jul 2024 15:23:47 -0700
Post by Chris M. Thomasson
Post by Michael S
On Sun, 07 Jul 2024 15:17:34 -0700
Post by Keith Thompson
I just about always use NULL, not 0, when I want a null pointer
constant. Similarly, I use '\0', not 0, when I want a null
character, 0.0 when I want a floating-point zero, and false when I
want a Boolean zero. I just like being explicit.
Pointer: I very rarely use NULL.
Character: I never use '\0'.
#define CLINE 128
char x[CLINE] = { '\0' };
?
;^)
I see nothing special about your case. {0} is the most appropriate.
And, BTW, I never use #define for integer constants.
Post by Chris M. Thomasson
Post by Michael S
Floating point: I never use 0.0.
Boolean: I use false much more often than 0.
Tim Rentsch
2024-07-09 11:32:50 UTC
Permalink
Post by Michael S
On Mon, 8 Jul 2024 15:23:47 -0700
Post by Chris M. Thomasson
Post by Michael S
On Sun, 07 Jul 2024 15:17:34 -0700
Post by Keith Thompson
I just about always use NULL, not 0, when I want a null pointer
constant. Similarly, I use '\0', not 0, when I want a null
character, 0.0 when I want a floating-point zero, and false when I
want a Boolean zero. I just like being explicit.
Pointer: I very rarely use NULL.
Character: I never use '\0'.
#define CLINE 128
char x[CLINE] = { '\0' };
?
;^)
I see nothing special about your case. {0} is the most appropriate.
Any use of '\0' almost always strikes me as an affectation. It's
like people want to somehow pretend that it's not the same as
just 0.
Post by Michael S
And, BTW, I never use #define for integer constants.
What do you do if you need to define a compile-time constant
whose value is outside the range of signed int? With the
understanding that the context is C as it is now, and not
C++ or some imagined other language.
Thiago Adams
2024-07-09 12:10:54 UTC
Permalink
Post by Tim Rentsch
Any use of '\0' almost always strikes me as an affectation. It's
like people want to somehow pretend that it's not the same as
just 0.
I like to pretend

'\0' is not int
2 > 1 is not int
etc

I know it is int, but I think this needs a redesign in C.
Meanwhile compilers can just have the type "int" and sub-type.

I don't like to think '\0' is null pointer.

int * p = '\0';
Tim Rentsch
2024-07-09 14:52:17 UTC
Permalink
Post by Thiago Adams
Post by Tim Rentsch
Any use of '\0' almost always strikes me as an affectation. It's
like people want to somehow pretend that it's not the same as
just 0.
I like to pretend
'\0' is not int
2 > 1 is not int
etc
I know it is int, but I think this needs a redesign in C.
I strongly encourage you not to do that. Based on past
experience most of your ideas for improvements make
things worse rather than better.
Thiago Adams
2024-07-09 16:16:22 UTC
Permalink
Post by Tim Rentsch
Post by Thiago Adams
Post by Tim Rentsch
Any use of '\0' almost always strikes me as an affectation. It's
like people want to somehow pretend that it's not the same as
just 0.
I like to pretend
'\0' is not int
2 > 1 is not int
etc
I know it is int, but I think this needs a redesign in C.
I strongly encourage you not to do that. Based on past
experience most of your ideas for improvements make
things worse rather than better.
It is only for static analysis.

For instance:


enum E {Z = 0};

int main()
{
int * p;
p = '\0';
p = false;
p = Z;
}

clang has 3 warnings for this code.

https://godbolt.org/z/56fn5PT4h

Especially for p = Z and p = '\0' we have value 0 of type int, but the
compiler is not blind for the other characteristics.
Tim Rentsch
2024-07-09 21:22:15 UTC
Permalink
Post by Thiago Adams
Post by Tim Rentsch
Post by Thiago Adams
Post by Tim Rentsch
Any use of '\0' almost always strikes me as an affectation. It's
like people want to somehow pretend that it's not the same as
just 0.
I like to pretend
'\0' is not int
2 > 1 is not int
etc
I know it is int, but I think this needs a redesign in C.
I strongly encourage you not to do that. Based on past
experience most of your ideas for improvements make
things worse rather than better.
It is only for static analysis.
enum E {Z = 0};
int main()
{
int * p;
p = '\0';
p = false;
p = Z;
}
clang has 3 warnings for this code.
https://godbolt.org/z/56fn5PT4h
Especially for p = Z and p = '\0' we have value 0 of type int, but the
compiler is not blind for the other characteristics.
You could give a master class in missing the point.
Kaz Kylheku
2024-07-09 22:25:34 UTC
Permalink
Post by Thiago Adams
Post by Tim Rentsch
Any use of '\0' almost always strikes me as an affectation. It's
like people want to somehow pretend that it's not the same as
just 0.
I like to pretend
'\0' is not int
In C++ it isn't.

void foo(int);
void foo(char);

foo(0); // takes int overload
foo('\0'); // takes char overload
Post by Thiago Adams
I don't like to think '\0' is null pointer.
I don't like that 1 - 1 is a null pointer. It's not a good design.

Nobody other than C humorists needs any zero-valued integer expression
whatsoever to be a null pointer constant.

How it should work is that only the token 0 is a null pointer constant.
Not 0L (ideally, not even 00 or 0x0, only the decimal token).

All zero-valued constant expressions of integer type should not be
null pointer constants, but ordinary expressions whch require
a cast to be converted to pointer type, and denote an address
associated with zero that may be different from the null pointer.
--
TXR Programming Language: http://nongnu.org/txr
Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal
Mastodon: @***@mstdn.ca
Thiago Adams
2024-07-10 11:50:24 UTC
Permalink
Post by Kaz Kylheku
Post by Thiago Adams
Post by Tim Rentsch
Any use of '\0' almost always strikes me as an affectation. It's
like people want to somehow pretend that it's not the same as
just 0.
I like to pretend
'\0' is not int
In C++ it isn't.
Yes

Yes there are several differences in C++.
Michael S
2024-07-09 12:50:14 UTC
Permalink
On Tue, 09 Jul 2024 04:32:50 -0700
Post by Tim Rentsch
Post by Michael S
On Mon, 8 Jul 2024 15:23:47 -0700
Post by Chris M. Thomasson
Post by Michael S
On Sun, 07 Jul 2024 15:17:34 -0700
Post by Keith Thompson
I just about always use NULL, not 0, when I want a null pointer
constant. Similarly, I use '\0', not 0, when I want a null
character, 0.0 when I want a floating-point zero, and false when
I want a Boolean zero. I just like being explicit.
Pointer: I very rarely use NULL.
Character: I never use '\0'.
#define CLINE 128
char x[CLINE] = { '\0' };
?
;^)
I see nothing special about your case. {0} is the most appropriate.
Any use of '\0' almost always strikes me as an affectation. It's
like people want to somehow pretend that it's not the same as
just 0.
Post by Michael S
And, BTW, I never use #define for integer constants.
What do you do if you need to define a compile-time constant
whose value is outside the range of signed int? With the
understanding that the context is C as it is now, and not
C++ or some imagined other language.
In comment above "integer constant" meant "within the range of signed
int". But let's accept more general meaning. Then, when it happens, I
have a problem and forced to flex my principles :(
Luckily, it's pretty rare. I mean, it's pretty rare that the constant
is both outside the range of signed int and I really really have to
have it as compile-time constant. More often big numbers like these are
used in arithmetic/logic, so 'const wide_type' or 'static const
wide_type' is practically as good as a "real" compile-time constant
despite being "less constant" in theory.
Tim Rentsch
2024-07-09 14:50:59 UTC
Permalink
Post by Michael S
On Tue, 09 Jul 2024 04:32:50 -0700
Post by Tim Rentsch
Post by Michael S
On Mon, 8 Jul 2024 15:23:47 -0700
Post by Chris M. Thomasson
Post by Michael S
On Sun, 07 Jul 2024 15:17:34 -0700
Post by Keith Thompson
I just about always use NULL, not 0, when I want a null pointer
constant. Similarly, I use '\0', not 0, when I want a null
character, 0.0 when I want a floating-point zero, and false when
I want a Boolean zero. I just like being explicit.
Pointer: I very rarely use NULL.
Character: I never use '\0'.
#define CLINE 128
char x[CLINE] = { '\0' };
?
;^)
I see nothing special about your case. {0} is the most appropriate.
Any use of '\0' almost always strikes me as an affectation. It's
like people want to somehow pretend that it's not the same as
just 0.
Post by Michael S
And, BTW, I never use #define for integer constants.
What do you do if you need to define a compile-time constant
whose value is outside the range of signed int? With the
understanding that the context is C as it is now, and not
C++ or some imagined other language.
In comment above "integer constant" meant "within the range of signed
int". But let's accept more general meaning. Then, when it happens, I
have a problem and forced to flex my principles :(
Luckily, it's pretty rare. I mean, it's pretty rare that the constant
is both outside the range of signed int and I really really have to
have it as compile-time constant.
I agree it's not common. I was just wondering what you would
do if it came up (and as it happens it did come up for me
recently, and I used a #define rather than trying to find an
alternative).
Post by Michael S
More often big numbers like these are
used in arithmetic/logic, so 'const wide_type' or 'static const
wide_type' is practically as good as a "real" compile-time constant
despite being "less constant" in theory.
I routinely use initialized ordinary variables rather than
other methods, when the variables work. Incidentally, IME
the results are better with automatic variables rather than
static. For arrays or structs, static might be better, but
for simple scalar values I normally use ordinary automatics
rather than statics.
David Brown
2024-07-09 16:19:20 UTC
Permalink
Post by Michael S
On Tue, 09 Jul 2024 04:32:50 -0700
Post by Tim Rentsch
Post by Michael S
On Mon, 8 Jul 2024 15:23:47 -0700
Post by Chris M. Thomasson
Post by Michael S
On Sun, 07 Jul 2024 15:17:34 -0700
Post by Keith Thompson
I just about always use NULL, not 0, when I want a null pointer
constant. Similarly, I use '\0', not 0, when I want a null
character, 0.0 when I want a floating-point zero, and false when
I want a Boolean zero. I just like being explicit.
Pointer: I very rarely use NULL.
Character: I never use '\0'.
#define CLINE 128
char x[CLINE] = { '\0' };
?
;^)
I see nothing special about your case. {0} is the most appropriate.
Any use of '\0' almost always strikes me as an affectation. It's
like people want to somehow pretend that it's not the same as
just 0.
Post by Michael S
And, BTW, I never use #define for integer constants.
What do you do if you need to define a compile-time constant
whose value is outside the range of signed int? With the
understanding that the context is C as it is now, and not
C++ or some imagined other language.
In comment above "integer constant" meant "within the range of signed
int". But let's accept more general meaning. Then, when it happens, I
have a problem and forced to flex my principles :(
Luckily, it's pretty rare. I mean, it's pretty rare that the constant
is both outside the range of signed int and I really really have to
have it as compile-time constant. More often big numbers like these are
used in arithmetic/logic, so 'const wide_type' or 'static const
wide_type' is practically as good as a "real" compile-time constant
despite being "less constant" in theory.
static const of the appropriate type should be as good as a define'd
value in almost any circumstance (assuming, of course, an optimising
compiler).

There are circumstances where you can use an enumeration constant as a
named integer constant, but where a static const int value cannot be
used, such as the size of statically allocated arrays. But you are very
unlikely to need such a large value to be an integer constant, rather
than just a value that the compiler sees as a compile-time constant for
optimisation purposes.

(And C23 helpfully allows enum values that are of larger integer types.
And also "constexpr" declarations.)
Kaz Kylheku
2024-07-09 02:49:49 UTC
Permalink
Post by Michael S
On Sun, 07 Jul 2024 15:17:34 -0700
Post by Keith Thompson
I just about always use NULL, not 0, when I want a null pointer
constant. Similarly, I use '\0', not 0, when I want a null character,
0.0 when I want a floating-point zero, and false when I want a Boolean
zero. I just like being explicit.
Pointer: I very rarely use NULL.
Character: I never use '\0'.
Floating point: I never use 0.0.
Never say never!

printf("%f\n", 0); // undefined behavior.
printf("%f\n", 0.0); // correct

If you're #define-ing a floating-point constant that has
no fractional part, you should put that .0 there.

Someone's going to pass your constant as a variadic argument,
where it doesn't convert to floating-point.

Also:

1/3 -> 0
1/3.0 -> 0.33333...

If you're #define-ing a floating point constant that has
no fractional part, and don't include the .0, and the
programmer uses it as a division denominator thinking that
it's a floating-point quantity, oops!
--
TXR Programming Language: http://nongnu.org/txr
Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal
Mastodon: @***@mstdn.ca
Michael S
2024-07-09 08:00:19 UTC
Permalink
On Tue, 9 Jul 2024 02:49:49 -0000 (UTC)
Post by Kaz Kylheku
Post by Michael S
On Sun, 07 Jul 2024 15:17:34 -0700
Post by Keith Thompson
I just about always use NULL, not 0, when I want a null pointer
constant. Similarly, I use '\0', not 0, when I want a null
character, 0.0 when I want a floating-point zero, and false when I
want a Boolean zero. I just like being explicit.
Pointer: I very rarely use NULL.
Character: I never use '\0'.
Floating point: I never use 0.0.
Never say never!
printf("%f\n", 0); // undefined behavior.
printf("%f\n", 0.0); // correct
Yes, but that's extremely rare that I want constant (except string
literal) as variable argument to printf().
Post by Kaz Kylheku
If you're #define-ing a floating-point constant that has
no fractional part, you should put that .0 there.
I am trying hard to avoid #define-ing floating-point constants.
In rare cases where it is not avoidable, most often the constant does
have fractional part. I am not sure what I would prefer when I can't
avoid #define-ing and the constant has no fractional part. Will I write
something like '#define ANSWER ((double)42)' or (42.0) ?
It depends on the mood of the minute.
Post by Kaz Kylheku
Someone's going to pass your constant as a variadic argument,
where it doesn't convert to floating-point.
1/3 -> 0
1/3.0 -> 0.33333...
If you're #define-ing a floating point constant that has
no fractional part, and don't include the .0, and the
programmer uses it as a division denominator thinking that
it's a floating-point quantity, oops!
Kaz Kylheku
2024-07-09 08:21:02 UTC
Permalink
Post by Michael S
On Tue, 9 Jul 2024 02:49:49 -0000 (UTC)
Post by Kaz Kylheku
Post by Michael S
On Sun, 07 Jul 2024 15:17:34 -0700
Post by Keith Thompson
I just about always use NULL, not 0, when I want a null pointer
constant. Similarly, I use '\0', not 0, when I want a null
character, 0.0 when I want a floating-point zero, and false when I
want a Boolean zero. I just like being explicit.
Pointer: I very rarely use NULL.
Character: I never use '\0'.
Floating point: I never use 0.0.
Never say never!
printf("%f\n", 0); // undefined behavior.
printf("%f\n", 0.0); // correct
Yes, but that's extremely rare that I want constant (except string
literal) as variable argument to printf().
Under the paradigm of "I write code only for myself", almost
anything is justifiable.

The "I want" stuff goes out the window as soon as your source code is
consumed by other programmers. (Interfaced with, patched, taken
over by ...). Anything you define could be used in ways you wouldn't
do yourself.


// #define GRAV 9.81
#define GRAV 3

...

printf("configured with\n");
...
printf("GRAV=%g\n", GRAV);
Post by Michael S
Post by Kaz Kylheku
If you're #define-ing a floating-point constant that has
no fractional part, you should put that .0 there.
I am trying hard to avoid #define-ing floating-point constants.
In rare cases where it is not avoidable, most often the constant does
have fractional part. I am not sure what I would prefer when I can't
avoid #define-ing and the constant has no fractional part. Will I write
something like '#define ANSWER ((double)42)' or (42.0) ?
It depends on the mood of the minute.
You don't need parentheses around 42.0, because the floating point
dot has a higher precedence than any operator. :-)
--
TXR Programming Language: http://nongnu.org/txr
Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal
Mastodon: @***@mstdn.ca
Tim Rentsch
2024-07-09 10:57:49 UTC
Permalink
Post by Michael S
On Tue, 9 Jul 2024 02:49:49 -0000 (UTC)
Post by Kaz Kylheku
Post by Michael S
On Sun, 07 Jul 2024 15:17:34 -0700
Post by Keith Thompson
I just about always use NULL, not 0, when I want a null pointer
constant. Similarly, I use '\0', not 0, when I want a null
character, 0.0 when I want a floating-point zero, and false when I
want a Boolean zero. I just like being explicit.
Pointer: I very rarely use NULL.
Character: I never use '\0'.
Floating point: I never use 0.0.
Never say never!
printf("%f\n", 0); // undefined behavior.
printf("%f\n", 0.0); // correct
Yes, but that's extremely rare that I want constant (except string
literal) as variable argument to printf().
Post by Kaz Kylheku
If you're #define-ing a floating-point constant that has
no fractional part, you should put that .0 there.
I am trying hard to avoid #define-ing floating-point constants.
In rare cases where it is not avoidable, most often the constant does
have fractional part. I am not sure what I would prefer when I can't
avoid #define-ing and the constant has no fractional part. Will I write
something like '#define ANSWER ((double)42)' or (42.0) ?
It depends on the mood of the minute.
Normally I would leave off the final 0 and just write 42.

Alternatively, a floating-point 42 can be written 42e0,
which stands out a little more than just using a trailing
dot.
Tim Rentsch
2024-07-09 03:17:37 UTC
Permalink
Post by Michael S
On Sun, 07 Jul 2024 15:17:34 -0700
Post by Keith Thompson
I just about always use NULL, not 0, when I want a null pointer
constant. Similarly, I use '\0', not 0, when I want a null character,
0.0 when I want a floating-point zero, and false when I want a Boolean
zero. I just like being explicit.
Pointer: I very rarely use NULL.
Character: I never use '\0'.
Floating point: I never use 0.0.
Boolean: I use false much more often than 0.
This posting has inspired me to try using (long)0.0
whenever a null pointer constant is needed. As for
example

(void*){ (long)0.0 }

as an argument to a variadic function where a pointer
is expected.
Keith Thompson
2024-07-09 04:01:44 UTC
Permalink
Tim Rentsch <***@z991.linuxsc.com> writes:
[...]
Post by Tim Rentsch
This posting has inspired me to try using (long)0.0
whenever a null pointer constant is needed. As for
example
(void*){ (long)0.0 }
as an argument to a variadic function where a pointer
is expected.
But surely ((void*)('/'/'/'-'/'/'/')) is more elegant.
--
Keith Thompson (The_Other_Keith) Keith.S.Thompson+***@gmail.com
void Void(void) { Void(); } /* The recursive call of the void */
Chris M. Thomasson
2024-07-09 05:06:48 UTC
Permalink
Post by Keith Thompson
[...]
Post by Tim Rentsch
This posting has inspired me to try using (long)0.0
whenever a null pointer constant is needed. As for
example
(void*){ (long)0.0 }
as an argument to a variadic function where a pointer
is expected.
But surely ((void*)('/'/'/'-'/'/'/')) is more elegant.
Who is surely? lol!



;^)
Tim Rentsch
2024-07-10 14:51:58 UTC
Permalink
Post by Keith Thompson
[...]
Post by Tim Rentsch
This posting has inspired me to try using (long)0.0
whenever a null pointer constant is needed. As for
example
(void*){ (long)0.0 }
as an argument to a variadic function where a pointer
is expected.
But surely ((void*)('/'/'/'-'/'/'/')) is more elegant.
Surely not. Furthermore the form I showed has a point,
whereas this example is roughly the equivalent of a
first grade knock-knock joke.
Keith Thompson
2024-07-10 21:23:06 UTC
Permalink
Post by Tim Rentsch
Post by Keith Thompson
[...]
Post by Tim Rentsch
This posting has inspired me to try using (long)0.0
whenever a null pointer constant is needed. As for
example
(void*){ (long)0.0 }
as an argument to a variadic function where a pointer
is expected.
But surely ((void*)('/'/'/'-'/'/'/')) is more elegant.
Surely not. Furthermore the form I showed has a point,
whereas this example is roughly the equivalent of a
first grade knock-knock joke.
I was of course joking. I assumed you were as well.

What is the point of (void*){ (long)0.0 }? I don't believe it's a null
pointer constant even in C23. My example is.
--
Keith Thompson (The_Other_Keith) Keith.S.Thompson+***@gmail.com
void Void(void) { Void(); } /* The recursive call of the void */
James Kuyper
2024-07-10 22:50:00 UTC
Permalink
Post by Keith Thompson
[...]
Post by Tim Rentsch
This posting has inspired me to try using (long)0.0
whenever a null pointer constant is needed. As for
example
(void*){ (long)0.0 }
as an argument to a variadic function where a pointer
is expected.
But surely ((void*)('/'/'/'-'/'/'/')) is more elegant.
Surely not. Furthermore the form I showed has a point,
whereas this example is roughly the equivalent of a
first grade knock-knock joke.
I was of course joking. I assumed you were as well.
What is the point of (void*){ (long)0.0 }? I don't believe it's a null
pointer constant even in C23.
I think you're right about that.

"An integer constant expression132) ... shall only have operands that
are ... compound literal constants of arithmetic type that are the
immediate operands of casts. ... Cast operators in an integer constant
expression shall only convert arithmetic types to integer types, ...",
so (long)0.0 is permitted."

While (void*) looks like a cast, in this context it is a compound
literal of pointer type, which is not allowed. If he had written

(void*)(long)0.0

that would not have been a problem.
Andrey Tarasevich
2024-07-09 04:45:25 UTC
Permalink
Post by Keith Thompson
I just about always use NULL, not 0, when I want a null pointer
constant. Similarly, I use '\0', not 0, when I want a null character,
0.0 when I want a floating-point zero, and false when I want a Boolean
zero. I just like being explicit.
Me too.

But at the same time I realize that this is a habit forced upon my by
circumstances, by necessity. C (as well as C++) at its beginning (and
when I started to use the language) was not very well-suited for
type-agnostic/DRY programming. It had a few odd features/idioms
acknowledging the possibility, but by large both languages were
predominantly type-aware or type-explicit. I reckon, this is actually
what made you to "like" such explicitness. But it is pointless to talk
about "liking" something, when one really had no choice.

The moment C++ realized the full power of generic/template programming,
it immediately rushed head-over-heels into type-agnostic programming
style. It was `auto` and `decltype` initially, which then just opened
the proverbial floodgates, triggering the avalanche of additional
features targeted at the type-agnostic programming style. Many in C++
world still protest it, claiming that old-style type-explicit code is
"easier to read", but they are nothing more than overgrown kids being
reluctant to take the training wheels off their bikes (since they make
it "easier to ride"). There no doubt anymore than type-agnostic
programming is the next big thing for C++.

The same goes for C. C is not C++, of course, but with the introduction
of `typeof` in C23 and, hopefully, better `_Generic` appearing one of
these days, one can hope that being type-explicit is a thing of the past
in C as well.

So, no. While I too prefer to use `NULL` for pointers and '\0' for
character constants, I realize that do it out of deep-seated habit, or
for nostalgic/luddite reasons mostly. Plain undecorated `0` as a
universal type-agnostic constant should really be my choice everywhere
today.
--
Best regards,
Andrey
Andrey Tarasevich
2024-07-09 04:49:10 UTC
Permalink
Post by Andrey Tarasevich
So, no. While I too prefer to use `NULL` for pointers and '\0' for
character constants, I realize that do it out of deep-seated habit, or
for nostalgic/luddite reasons mostly. Plain undecorated `0` as a
universal type-agnostic constant should really be my choice everywhere
today.
... although, one the second thought, one can probably start a Holy War
about what a proper type-agnostic declaration of a `double` variable
should look like

double d = 0;

or

auto d = 0.0;
--
Best regards,
Andrey
Keith Thompson
2024-07-09 05:58:20 UTC
Permalink
Post by Tim Rentsch
Post by Keith Thompson
I just about always use NULL, not 0, when I want a null pointer
constant. Similarly, I use '\0', not 0, when I want a null character,
0.0 when I want a floating-point zero, and false when I want a Boolean
zero. I just like being explicit.
Me too.
But at the same time I realize that this is a habit forced upon my by
circumstances, by necessity. C (as well as C++) at its beginning (and
when I started to use the language) was not very well-suited for
type-agnostic/DRY programming. It had a few odd features/idioms
acknowledging the possibility, but by large both languages were
predominantly type-aware or type-explicit. I reckon, this is actually
what made you to "like" such explicitness. But it is pointless to talk
about "liking" something, when one really had no choice.
The moment C++ realized the full power of generic/template
programming, it immediately rushed head-over-heels into type-agnostic
programming style. It was `auto` and `decltype` initially, which then
just opened the proverbial floodgates, triggering the avalanche of
additional features targeted at the type-agnostic programming
style. Many in C++ world still protest it, claiming that old-style
type-explicit code is "easier to read", but they are nothing more than
overgrown kids being reluctant to take the training wheels off their
bikes (since they make it "easier to ride"). There no doubt anymore
than type-agnostic programming is the next big thing for C++.
The same goes for C. C is not C++, of course, but with the
introduction of `typeof` in C23 and, hopefully, better `_Generic`
appearing one of these days, one can hope that being type-explicit is
a thing of the past in C as well.
So, no. While I too prefer to use `NULL` for pointers and '\0' for
character constants, I realize that do it out of deep-seated habit, or
for nostalgic/luddite reasons mostly. Plain undecorated `0` as a
universal type-agnostic constant should really be my choice everywhere
today.
Hmm. I like the idea of a type-agnostic way to express a "zero" value,
especially in a language that lets you write type-generic code. But I
don't think I like using 0 for that purpose, since 0 is *also* a
constant of the specific type int. C's use of 0 for all scalar types
strikes me more as an historical accident than a design feature.

And of course not all code needs to be type-agnostic.

In C++, {} seems to be an expression that gives you the default value of
any type (there are probably off-topic subtleties I'm missing). In C23,
it can be used as an initializer ({0} works in C17 and earlier), but
not as an expression.
--
Keith Thompson (The_Other_Keith) Keith.S.Thompson+***@gmail.com
void Void(void) { Void(); } /* The recursive call of the void */
Tim Rentsch
2024-07-10 14:36:14 UTC
Permalink
Post by Keith Thompson
Hmm. I like the idea of a type-agnostic way to express a "zero"
value, [but] C's use of 0 for all scalar types strikes me more as
an historical accident than a design feature.
I don't think it was an accident at all. It was chosen to be
consistent with how if(), while(), !, ?:, and so forth, all act.
There is a very consistent design philosophy there. Sometimes
people who come from a strong Pascal background don't like it,
but personally I find the C model easier and more convenient to
work with than the Pascal model.
Keith Thompson
2024-07-10 21:15:29 UTC
Permalink
Post by Tim Rentsch
Post by Keith Thompson
Hmm. I like the idea of a type-agnostic way to express a "zero"
value, [but] C's use of 0 for all scalar types strikes me more as
an historical accident than a design feature.
I don't think it was an accident at all. It was chosen to be
consistent with how if(), while(), !, ?:, and so forth, all act.
There is a very consistent design philosophy there. Sometimes
people who come from a strong Pascal background don't like it,
but personally I find the C model easier and more convenient to
work with than the Pascal model.
In early C, int was in a very real sense the default type. In B,
types weren't even explicit, and IIRC variables were effectively "of
type int", or more precisely a 16-bit PDP-11 word. (I'm glossing
over some details of B, many of which I don't know). In that
context 0 made sense as a general-purpose "zero" value.

Modern C has moved away from making int some kind of default
(though it hasn't entirely done so).

What I dislike is the fact that 0 is *both* of the specific type
int *and* is commonly used as a general-purpose scalar 0.

I accept it because it's the way the language is defined, but
IMHO it's perhaps not an historical accident (you're right, it was
deliberate), but more of an historical relic.

Which is why I use 0 for integers, '\0' for characters, 0.0 for
floating-point, and NULL (or nullptr if it's available) for pointers.
If there were some general-purpose zero token that *isn't* of a
specific type (I mentioned "{}" upthread), I'd probably use that.
But it's not enough of a problem that I'd necessarily advocate a
language change. And if someone else consistently uses 0 in pointer
context, I'll waste about half a second being annoyed and then move on.
--
Keith Thompson (The_Other_Keith) Keith.S.Thompson+***@gmail.com
void Void(void) { Void(); } /* The recursive call of the void */
Ben Bacarisse
2024-07-07 23:42:02 UTC
Permalink
Post by Scott Lurndal
Post by Ben Bacarisse
Post by Scott Lurndal
Post by Ben Bacarisse
Post by Scott Lurndal
Post by Janis Papanagnou
Post by Kaz Kylheku
Post by Thiago Adams
If you were creating C code today and could use a C23 compiler, would
you use nullptr instead of NULL?
char *p = 0;
I was still 20 something when I (easily) wrapped my head around the 0
null pointer constant, and have not had any problems with it.
Once I learned the standard-defined truth about null pointer constants,
and their relationship to the NULL macro, I dropped NULL like a hot
potato, and didn't look back (except when working in code bases that use
NULL).
We also used 0 as "universal" pointer value regularly without problems.
I also like to use 0, but I'm not sure I could say exactly why. Maybe
because of pre-C exposure (B and BCPL).
Post by Scott Lurndal
Whereas I spent 6 years programming on an architecture[*] where a
null pointer was represented in hardware by the value 0xc0eeeeee. I always
use the NULL macro in both C and C++ code.
I'm sure you know (but maybe some other readers might not) that that
does not stop one using 0 in C source code. Whatever a null pointer
"really" is on some hardware, 0 must work in C, including in comparisons
with == and !=. You can have
Yes. However, I consider that ambiguous, I prefer to be explicit and
use NULL or nullptr.
In what sense is using 0 ambiguous? I can't see it.
the digit zero is context dependent, which makes it ambiguous.
Ah. I thought we were talking about a pointer context so I thought you
meant that using 0 in a pointer context was ambiguous. In

char *p = 0;

the 0 is not ambiguous (i.e. open to more than one meaning). It's open
to being misunderstood by people who don't know C, but that true of the
'char', the '*' and the '=' (and possibly the 'p' and the ';' too).
Post by Scott Lurndal
I.e. it can either be a null pointer or the value zero
depending on context, which makes it ambiguous to the casual
reader. Particularly when reading code that someone
else has written. NULL makes the programmers intent crystal
clear.
That's a rather niche readership -- one that might consider

char *p = 0;

unclear. Do you want such people reading your C code with a view to
working on it?

I find myself completely out of step with many posters here about
"explicit code" should look like. I think

char *p = 0;

is explicit enough and, in fact, I consider it a plus point if someone
reading it goes "hey, what's going on here?" and ends up learning that 0
is null pointer constant in C. They may, along the way, learn a few
other things that they should also know before fiddling with the code.
At the very least, they will have learnt that they don't know it all.
--
Ben.
Kaz Kylheku
2024-07-08 07:19:09 UTC
Permalink
Post by Ben Bacarisse
I find myself completely out of step with many posters here about
"explicit code" should look like. I think
char *p = 0;
is explicit enough and, in fact, I consider it a plus point if someone
reading it goes "hey, what's going on here?" and ends up learning that 0
is null pointer constant in C.
And if that person is on the C or C++ langauge committee, that bit of
learning could just prevent a superfluous non-invention like nullptr.
--
TXR Programming Language: http://nongnu.org/txr
Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal
Mastodon: @***@mstdn.ca
Janis Papanagnou
2024-07-08 09:08:53 UTC
Permalink
Post by Kaz Kylheku
Post by Ben Bacarisse
I find myself completely out of step with many posters here about
"explicit code" should look like. I think
char *p = 0;
is explicit enough and, in fact, I consider it a plus point if someone
reading it goes "hey, what's going on here?" and ends up learning that 0
is null pointer constant in C.
And if that person is on the C or C++ langauge committee, that bit of
learning could just prevent a superfluous non-invention like nullptr.
What's superfluous to one is useful for others (e.g. for grep'ing
occurrences of a null-pointer value in source codes); if it's not
defined in a standard it gets explicitly defined individually, and
then likely in different (non-uniform, non-standard) ways.

To me it's more likely that because of that it had been deliberately
added to support such desires, and less likely that the C-standards
folks need to learn "C" and wouldn't know what 0 as a pointer value
would mean or that it has a clear semantic in such pointer contexts.

Janis
Ben Bacarisse
2024-07-08 10:18:54 UTC
Permalink
Post by Janis Papanagnou
Post by Kaz Kylheku
Post by Ben Bacarisse
I find myself completely out of step with many posters here about
"explicit code" should look like. I think
char *p = 0;
is explicit enough and, in fact, I consider it a plus point if someone
reading it goes "hey, what's going on here?" and ends up learning that 0
is null pointer constant in C.
And if that person is on the C or C++ langauge committee, that bit of
learning could just prevent a superfluous non-invention like nullptr.
What's superfluous to one is useful for others (e.g. for grep'ing
occurrences of a null-pointer value in source codes);
This is been suggested twice now but I'm struggling to see why that is
useful. I can see management wanting one to find all uses of a null
pointer constant to check that they have all been replaced by the
"safer" nullptr, but what's the value in searching for nullptr?
Post by Janis Papanagnou
if it's not
defined in a standard it gets explicitly defined individually, and
then likely in different (non-uniform, non-standard) ways.
To me it's more likely that because of that it had been deliberately
added to support such desires,
That would be a sound suggestion if "such desires" could be explained.
Until then, I suggest it is simply harmonisation with C++. C now has
true and false, [[...]] attributes, typeof, __has_include and no doubt
quite a few more I've forgotten. nullptr is, until some other argument
can be made, just another one of those.
Post by Janis Papanagnou
and less likely that the C-standards
folks need to learn "C" and wouldn't know what 0 as a pointer value
would mean or that it has a clear semantic in such pointer contexts.
--
Ben.
Janis Papanagnou
2024-07-08 10:29:23 UTC
Permalink
Post by Ben Bacarisse
Post by Janis Papanagnou
What's superfluous to one is useful for others (e.g. for grep'ing
occurrences of a null-pointer value in source codes);
This is been suggested twice now but I'm struggling to see why that is
useful. I can see management wanting one to find all uses of a null
pointer constant to check that they have all been replaced by the
"safer" nullptr, but what's the value in searching for nullptr?
Bug-tracking.

Janis
Post by Ben Bacarisse
[...]
Ben Bacarisse
2024-07-08 16:23:23 UTC
Permalink
Post by Janis Papanagnou
Post by Ben Bacarisse
Post by Janis Papanagnou
What's superfluous to one is useful for others (e.g. for grep'ing
occurrences of a null-pointer value in source codes);
This is been suggested twice now but I'm struggling to see why that is
useful. I can see management wanting one to find all uses of a null
pointer constant to check that they have all been replaced by the
"safer" nullptr, but what's the value in searching for nullptr?
Bug-tracking.
Can you say more?
--
Ben.
Janis Papanagnou
2024-07-08 18:07:26 UTC
Permalink
Post by Ben Bacarisse
Post by Janis Papanagnou
Post by Ben Bacarisse
Post by Janis Papanagnou
What's superfluous to one is useful for others (e.g. for grep'ing
occurrences of a null-pointer value in source codes);
This is been suggested twice now but I'm struggling to see why that is
useful. I can see management wanting one to find all uses of a null
pointer constant to check that they have all been replaced by the
"safer" nullptr, but what's the value in searching for nullptr?
Bug-tracking.
Can you say more?
Frankly, no. Not more than has been already written (not only by me
but also by others) in a couple posts of this thread. It's so clear to
me that if it's not obvious I don't know what would help to explain
(i.e. without going into micro-management explanations). - If yet you
haven't experienced a necessity for an alpha pattern for the value 0,
and since you're an experienced IT expert, I suppose it's okay for you
as it was. - When it had been introduced in our development standards
there was no second opinion. With C's primitive pointer concept we had
so often issues that it was helpful to quickly find them. The 'null'
we used was not the only convention, also suffixing pointer variables
with '_ptr' (or camel-case as 'Ptr' in C++) helped to quickly gain
insights, especially in (but not restricted to) code of others. Besides
bug-tracking we had also other QA measures like code inspections that
took advantage of more explicit naming supported by 'null' or '_ptr'.
We tried to express as much as possible ("as C allows") by conventions
and additions to a class library we were using. (Also things like the
elsethread disrespectfully mentioned 'true' and 'false' literals; but
since there was no first class boolean type as in more sophisticated
HLL of that time this could not address all issues; but at least make
the programmers' intention clearer - cf. false positives/negatives -
and bugs easier to find.)

Janis
Ben Bacarisse
2024-07-08 22:55:54 UTC
Permalink
Post by Janis Papanagnou
Post by Ben Bacarisse
Post by Janis Papanagnou
Post by Ben Bacarisse
Post by Janis Papanagnou
What's superfluous to one is useful for others (e.g. for grep'ing
occurrences of a null-pointer value in source codes);
This is been suggested twice now but I'm struggling to see why that is
useful. I can see management wanting one to find all uses of a null
pointer constant to check that they have all been replaced by the
"safer" nullptr, but what's the value in searching for nullptr?
Bug-tracking.
Can you say more?
Frankly, no.
OK.
--
Ben.
Janis Papanagnou
2024-07-10 15:28:54 UTC
Permalink
Post by Ben Bacarisse
Post by Janis Papanagnou
Post by Ben Bacarisse
Post by Janis Papanagnou
What's superfluous to one is useful for others (e.g. for grep'ing
occurrences of a null-pointer value in source codes);
This is been suggested twice now but I'm struggling to see why that is
useful. I can see management wanting one to find all uses of a null
pointer constant to check that they have all been replaced by the
"safer" nullptr, but what's the value in searching for nullptr?
Bug-tracking.
Can you say more?
Frankly, no. [...]
OK.
So the text you snipped from my reply did not trigger any insight?

Another, last try...
Compare it to 'enum' constants. When I code or debug I want to track
(search and find) them by name not by integer number.
Similar with the 'enum' bool type we introduced (when there was not
yet a bool type existing in C or C++) with literal constants 'true'
and 'false'. (Only two values, but still as important.)
Similar with the dedicated pointer value 0 (these days we used the
literal 'null'). (Only one value, still useful for tracking eq/ne
comparisons and initializations.)

Janis
Ben Bacarisse
2024-07-10 23:25:42 UTC
Permalink
Post by Janis Papanagnou
Post by Ben Bacarisse
Post by Janis Papanagnou
Post by Ben Bacarisse
Post by Janis Papanagnou
What's superfluous to one is useful for others (e.g. for grep'ing
occurrences of a null-pointer value in source codes);
This is been suggested twice now but I'm struggling to see why that is
useful. I can see management wanting one to find all uses of a null
pointer constant to check that they have all been replaced by the
"safer" nullptr, but what's the value in searching for nullptr?
Bug-tracking.
Can you say more?
Frankly, no. [...]
OK.
So the text you snipped from my reply did not trigger any insight?
I didn't read it. You said you could not say more so I assumed what
you'd written was not saying more but something else like repeating what
you'd already said.
Post by Janis Papanagnou
Another, last try...
Compare it to 'enum' constants. When I code or debug I want to track
(search and find) them by name not by integer number.
Similar with the 'enum' bool type we introduced (when there was not
yet a bool type existing in C or C++) with literal constants 'true'
and 'false'. (Only two values, but still as important.)
Similar with the dedicated pointer value 0 (these days we used the
literal 'null'). (Only one value, still useful for tracking eq/ne
comparisons and initializations.)
Yes, you've said that before. You want to search for nullptr. I can't
think of how that might help find a real bug, if that's what you mean by
bug-tracking.

I was hoping for a story... "Once I had this bug where... and if I'd
been using nullptr I'd have found it a day earlier" kind of thing. I'd
found a lot of bugs over the years, but I don't recall any that would
have been easier to find had I been able to search for nullptr.

I was looking for real-world insight here. Obviously one could make up
a bug where p = nullptr; was written where, say, p = null - ptr; was
intended, but that's not what I mean.

Without such an example, your argument seems to be overly generic.
Would you welcome the introduction of the keyword unity -- with the
value 1 and type int -- into C because one could then search for it?
--
Ben.
Kaz Kylheku
2024-07-09 02:32:46 UTC
Permalink
Post by Ben Bacarisse
Post by Janis Papanagnou
Post by Kaz Kylheku
Post by Ben Bacarisse
I find myself completely out of step with many posters here about
"explicit code" should look like. I think
char *p = 0;
is explicit enough and, in fact, I consider it a plus point if someone
reading it goes "hey, what's going on here?" and ends up learning that 0
is null pointer constant in C.
And if that person is on the C or C++ langauge committee, that bit of
learning could just prevent a superfluous non-invention like nullptr.
What's superfluous to one is useful for others (e.g. for grep'ing
occurrences of a null-pointer value in source codes);
This is been suggested twice now but I'm struggling to see why that is
useful. I can see management wanting one to find all uses of a null
pointer constant to check that they have all been replaced by the
"safer" nullptr, but what's the value in searching for nullptr?
We could patch GCC to have a -Wnull-ptr-zero, which will give you a
diagnostic for every occurrence of a zero valued integer expression that
becomes a null pointer constant rather than an integer or floating-point
value (and that isn't cast to pointer type).

(If this were so hugely useful, someone woulda done it by now?)

(Of course, it would go off on occurrences of NULL where NULL
is defined as just zero; the diagnostic could be clever enough
not to go off on expressions that are the expansion descendants
of NULL, or optionally so.)

(The option would actually be useful to someone wanting to convert
0 to NULL or nullptr.)

(Just like -Wold-style-cast in GNU C++ helps coders who only want
to use static_cast and friends.)
--
TXR Programming Language: http://nongnu.org/txr
Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal
Mastodon: @***@mstdn.ca
Chris M. Thomasson
2024-07-09 05:02:20 UTC
Permalink
Post by Kaz Kylheku
Post by Ben Bacarisse
Post by Janis Papanagnou
Post by Kaz Kylheku
Post by Ben Bacarisse
I find myself completely out of step with many posters here about
"explicit code" should look like. I think
char *p = 0;
is explicit enough and, in fact, I consider it a plus point if someone
reading it goes "hey, what's going on here?" and ends up learning that 0
is null pointer constant in C.
And if that person is on the C or C++ langauge committee, that bit of
learning could just prevent a superfluous non-invention like nullptr.
What's superfluous to one is useful for others (e.g. for grep'ing
occurrences of a null-pointer value in source codes);
This is been suggested twice now but I'm struggling to see why that is
useful. I can see management wanting one to find all uses of a null
pointer constant to check that they have all been replaced by the
"safer" nullptr, but what's the value in searching for nullptr?
We could patch GCC to have a -Wnull-ptr-zero, which will give you a
diagnostic for every occurrence of a zero valued integer expression that
becomes a null pointer constant rather than an integer or floating-point
value (and that isn't cast to pointer type).
I would not mind that! :^)

[...]
Ben Bacarisse
2024-07-09 09:21:56 UTC
Permalink
Post by Kaz Kylheku
Post by Ben Bacarisse
Post by Janis Papanagnou
Post by Kaz Kylheku
Post by Ben Bacarisse
I find myself completely out of step with many posters here about
"explicit code" should look like. I think
char *p = 0;
is explicit enough and, in fact, I consider it a plus point if someone
reading it goes "hey, what's going on here?" and ends up learning that 0
is null pointer constant in C.
And if that person is on the C or C++ langauge committee, that bit of
learning could just prevent a superfluous non-invention like nullptr.
What's superfluous to one is useful for others (e.g. for grep'ing
occurrences of a null-pointer value in source codes);
This is been suggested twice now but I'm struggling to see why that is
useful. I can see management wanting one to find all uses of a null
pointer constant to check that they have all been replaced by the
"safer" nullptr, but what's the value in searching for nullptr?
We could patch GCC to have a -Wnull-ptr-zero, which will give you a
diagnostic for every occurrence of a zero valued integer expression that
becomes a null pointer constant rather than an integer or floating-point
value (and that isn't cast to pointer type).
Sure.

I once tried to persuade the compiler team where I worked to write a
"tool box" for diagnostics that would have a meta-language in which
users could describe the conditions that wanted to be diagnosed. The
idea was half-baked so it never went anywhere.
--
Ben.
Chris M. Thomasson
2024-07-11 00:32:25 UTC
Permalink
[...]
Post by Ben Bacarisse
Post by Kaz Kylheku
We could patch GCC to have a -Wnull-ptr-zero, which will give you a
diagnostic for every occurrence of a zero valued integer expression that
becomes a null pointer constant rather than an integer or floating-point
value (and that isn't cast to pointer type).
Sure.
I once tried to persuade the compiler team where I worked to write a
"tool box" for diagnostics that would have a meta-language in which
users could describe the conditions that wanted to be diagnosed. The
idea was half-baked so it never went anywhere.
No funding?

Richard Damon
2024-07-08 11:18:18 UTC
Permalink
Post by Kaz Kylheku
Post by Ben Bacarisse
I find myself completely out of step with many posters here about
"explicit code" should look like. I think
char *p = 0;
is explicit enough and, in fact, I consider it a plus point if someone
reading it goes "hey, what's going on here?" and ends up learning that 0
is null pointer constant in C.
And if that person is on the C or C++ langauge committee, that bit of
learning could just prevent a superfluous non-invention like nullptr.
Remember, it was invented on the C++ side, where it has some very useful
uses due to overloading.

And then brought over to C to minimize the differences.

Nothing made it manditory, so if you want to make your reader learn more
about C, go ahead and use things that are somewhat obscure.
James Kuyper
2024-07-08 15:03:42 UTC
Permalink
...
Post by Ben Bacarisse
I.e. it can either be a null pointer or the value zero
depending on context, which makes it ambiguous to the casual
reader. Particularly when reading code that someone
else has written. NULL makes the programmers intent crystal
clear.
That's a rather niche readership -- one that might consider
char *p = 0;
unclear. Do you want such people reading your C code with a view to
working on it?
The problem is not "char p=0;". If you're sure what type p has, there's
no problem. The problem comes with code like "p=0", where "p=NULL" would
serve to remind you that p should be a pointer, while "p=nullptr"
guarantees a diagnostic if p is not a pointer. I have fixed bugs which
would have been caught a lot earlier if nullptr had existed, and had
been the only permitted kind of null pointer constant.
Kaz Kylheku
2024-07-09 02:45:19 UTC
Permalink
Post by James Kuyper
...
Post by Ben Bacarisse
I.e. it can either be a null pointer or the value zero
depending on context, which makes it ambiguous to the casual
reader. Particularly when reading code that someone
else has written. NULL makes the programmers intent crystal
clear.
That's a rather niche readership -- one that might consider
char *p = 0;
unclear. Do you want such people reading your C code with a view to
working on it?
The problem is not "char p=0;". If you're sure what type p has, there's
no problem. The problem comes with code like "p=0", where "p=NULL" would
serve to remind you that p should be a pointer, while "p=nullptr"
guarantees a diagnostic if p is not a pointer.
The programming world has moved away from tying syntax to concrete
implementation though. For every time you worry in p = 0,
p is floating, integer or pointer, a thousand coders somewhere
are doing writing obj.foo(), where the type of obj can be one of
half a dozen different things at run-time.

p = 0 is nicely generic: "make p null, whatever it is".

A pointer "responds" to this "method" by becoming null.

And anyway, if the expression is p + 3 instead, what tells you then
whether it's an integer, float or pointer. Should we have a
ptrplus keyword for displacing pointers?

Ancient C, or pre-C, had separate operators for floating-point,
prefixed with a hash: #+, #-, #*, ...
Post by James Kuyper
I have fixed bugs which
would have been caught a lot earlier if nullptr had existed, and had
been the only permitted kind of null pointer constant.
All the ones I remember were about 0 being used as a variadic
pointer argument, without a cast. I can't think of anywhere else
it would be a problem.

nullptr being the only null pointer constant would prevent that
where the type is void * or char *, (or where pointers of all types all
have the same representation).
--
TXR Programming Language: http://nongnu.org/txr
Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal
Mastodon: @***@mstdn.ca
Tim Rentsch
2024-07-07 03:36:09 UTC
Permalink
Post by Ben Bacarisse
Post by Janis Papanagnou
Post by Kaz Kylheku
Post by Thiago Adams
If you were creating C code today and could use a C23 compiler, would
you use nullptr instead of NULL?
char *p = 0;
I was still 20 something when I (easily) wrapped my head around the 0
null pointer constant, and have not had any problems with it.
Once I learned the standard-defined truth about null pointer constants,
and their relationship to the NULL macro, I dropped NULL like a hot
potato, and didn't look back (except when working in code bases that use
NULL).
We also used 0 as "universal" pointer value regularly without problems.
I also like to use 0, but I'm not sure I could say exactly why. Maybe
because of pre-C exposure (B and BCPL).
Me too. If I had to guess about why, I think I would say (1) being
used to it from the original K&R, and (2) it's philosophically
consistent with how if(), for(), while(), and logical expressions
work. Speaking for myself that consistency is worth a lot, and
using NULL sticks out like a sore thumb.
Kaz Kylheku
2024-07-06 22:11:02 UTC
Permalink
Post by Janis Papanagnou
Post by Kaz Kylheku
Post by Thiago Adams
If you were creating C code today and could use a C23 compiler, would
you use nullptr instead of NULL?
char *p = 0;
I was still 20 something when I (easily) wrapped my head around the 0
null pointer constant, and have not had any problems with it.
Once I learned the standard-defined truth about null pointer constants,
and their relationship to the NULL macro, I dropped NULL like a hot
potato, and didn't look back (except when working in code bases that use
NULL).
We also used 0 as "universal" pointer value regularly without problems.
Instead of inventing a new keyword "nullptr", the C++ people should have
made the 0p and 0P tokens have that meaning.

In the preprocessing phases, 0p and 0P are already pp-number tokens,
which are invalid tokens, requiring a diagnostic.
Post by Janis Papanagnou
One practical advantage of adding a named entity (with a value of 0)
was to easily grep (find) appearances of this value in source code.
0[Pp] ticks off that box. So does NULL.
--
TXR Programming Language: http://nongnu.org/txr
Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal
Mastodon: @***@mstdn.ca
bart
2024-07-06 13:51:19 UTC
Permalink
Post by Kaz Kylheku
Post by Thiago Adams
If you were creating C code today and could use a C23 compiler, would
you use nullptr instead of NULL?
char *p = 0;
I was still 20 something when I (easily) wrapped my head around the 0
null pointer constant, and have not had any problems with it.
Once I learned the standard-defined truth about null pointer constants,
and their relationship to the NULL macro, I dropped NULL like a hot
potato, and didn't look back (except when working in code bases that use
NULL).
Using actual zero for a pointer value is crass. This wouldn't work for
example:

char *p = 3;

Nor this:

int a = 0;
char *p = a;


Although this does:

char *p = 3/4;

And this:

enum {a=42, b=a};
char *p = a-b; // or a&1, but not a&2

It walks all over the language's type system, such as it is.
Lawrence D'Oliveiro
2024-07-07 04:55:14 UTC
Permalink
Post by bart
Using actual zero for a pointer value is crass. This wouldn't work for
char *p = 3;
But of course this does:

char *p = 0;

From the C23 spec, I found this footnote in §6.6:

A named constant or compound literal constant of integer type and
value zero is a null pointer constant. A named constant or
compound literal constant with a pointer type and a value null is
a null pointer but not a null pointer constant; it may only be
used to initialize a pointer object if its type implicitly
converts to the target type.

That first sentence is so important, you’d think it would be in the main
text somewhere.
Keith Thompson
2024-07-07 07:04:40 UTC
Permalink
Post by Kaz Kylheku
Post by bart
Using actual zero for a pointer value is crass. This wouldn't work for
char *p = 3;
char *p = 0;
A named constant or compound literal constant of integer type and
value zero is a null pointer constant. A named constant or
compound literal constant with a pointer type and a value null is
a null pointer but not a null pointer constant; it may only be
used to initialize a pointer object if its type implicitly
converts to the target type.
That first sentence is so important, you’d think it would be in the main
text somewhere.
The definition of "null pointer constant" is in N3220 6.3.2.3,
(Conversions, Other operands, Pointers):

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

6.6 makes it clear that named constants and compound literal constants
of integer type are integer constant expressions.
--
Keith Thompson (The_Other_Keith) Keith.S.Thompson+***@gmail.com
void Void(void) { Void(); } /* The recursive call of the void */
bart
2024-07-07 17:40:02 UTC
Permalink
Post by Kaz Kylheku
Post by bart
Using actual zero for a pointer value is crass. This wouldn't work for
char *p = 3;
char *p = 0;
A named constant or compound literal constant of integer type and
value zero is a null pointer constant. A named constant or
compound literal constant with a pointer type and a value null is
a null pointer but not a null pointer constant; it may only be
used to initialize a pointer object if its type implicitly
converts to the target type.
That first sentence is so important, you’d think it would be in the main
text somewhere.
It doesn't tell the full story, as you can have any arbitrary expression
of such terms that results in a suitable value:

char* p = width*height;

This is valid if width/height are enums and that area calculation yields
zero. But update values slightly and it no longer compiles.
Richard Damon
2024-07-06 14:39:57 UTC
Permalink
Post by Thiago Adams
If you were creating C code today and could use a C23 compiler, would
you use nullptr instead of NULL?
I am asking because I think I will keep using NULL.
I like nullptr semantics but I don't like to introduce new element
(nullptr) inside the code with no guarantee that the code will not mix both.
In the past we also didn't have a guarantee we are not mixing 0 or NULL.
I think the best scenario for a team guideline would be a style warning
if 0 or nullptr is used and NULL to be defined as nullptr in a C23 compiler.
The (small) problem with 0 or NULL being use is that in a context where
you THINK you are passing a pointer, but the function actually is taking
an integer value, 0 or NULL (defined as a 0) passes the syntax check.

If C23 REQURIED NULL to be defined as nullptr, then NULL would have been
used, but as far as I know, it is still allowed to be defined as 0
(unless you also have POSIX compatibility).

With POSIX Compatibility, where NULL must have the type of (void*) you
also avoid the possible error, and thus the desire to use nullptr.
David Brown
2024-07-06 16:57:08 UTC
Permalink
Post by Richard Damon
Post by Thiago Adams
If you were creating C code today and could use a C23 compiler, would
you use nullptr instead of NULL?
I am asking because I think I will keep using NULL.
I like nullptr semantics but I don't like to introduce new element
(nullptr) inside the code with no guarantee that the code will not mix both.
In the past we also didn't have a guarantee we are not mixing 0 or NULL.
I think the best scenario for a team guideline would be a style
warning if 0 or nullptr is used and NULL to be defined as nullptr in a
C23 compiler.
The (small) problem with 0 or NULL being use is that in a context where
you THINK you are passing a pointer, but the function actually is taking
an integer value, 0 or NULL (defined as a 0) passes the syntax check.
If C23 REQURIED NULL to be defined as nullptr, then NULL would have been
used, but as far as I know, it is still allowed to be defined as 0
(unless you also have POSIX compatibility).
With POSIX Compatibility, where NULL must have the type of (void*) you
also avoid the possible error, and thus the desire to use nullptr.
I hope that defining NULL as nullptr will become common - but I would be
surprised to ever see it being required by C standards.

The ideal would be for C libraries to define NULL as nullptr and for C
compilers to support a flag like gcc's "-Wzero-as-null-pointer-constant"
warning (it is currently C++ only). Then people can easily eliminate
any mixup between integer 0 and null pointer constants by using that
flag and either NULL or nullptr, according to taste. (And those who
don't want such checks, are not required to change.)
Lawrence D'Oliveiro
2024-07-07 08:00:18 UTC
Permalink
... and for C compilers to support a flag like gcc's "-Wzero-as-null
-pointer-constant" warning ...
The trouble with compiler flags is they can never be part of any language
spec.
David Brown
2024-07-07 10:07:35 UTC
Permalink
Post by Lawrence D'Oliveiro
... and for C compilers to support a flag like gcc's "-Wzero-as-null
-pointer-constant" warning ...
The trouble with compiler flags is they can never be part of any language
spec.
That is both their advantage, and their disadvantage.

Let the C standards define what the language requires when the source
code is correct, and have everyone agree on that. Let compiler
implementations go beyond that and give options that some might want,
and others not want. /I/ will probably use nullptr in C23 coding, and I
like tools to enforce my style (because I make mistakes) but I would
certainly not want to force others to change their style based on /my/
preferences.
Thiago Adams
2024-07-07 11:40:07 UTC
Permalink
Post by David Brown
Post by Richard Damon
Post by Thiago Adams
If you were creating C code today and could use a C23 compiler, would
you use nullptr instead of NULL?
I am asking because I think I will keep using NULL.
I like nullptr semantics but I don't like to introduce new element
(nullptr) inside the code with no guarantee that the code will not mix both.
In the past we also didn't have a guarantee we are not mixing 0 or NULL.
I think the best scenario for a team guideline would be a style
warning if 0 or nullptr is used and NULL to be defined as nullptr in
a C23 compiler.
The (small) problem with 0 or NULL being use is that in a context
where you THINK you are passing a pointer, but the function actually
is taking an integer value, 0 or NULL (defined as a 0) passes the
syntax check.
If C23 REQURIED NULL to be defined as nullptr, then NULL would have
been used, but as far as I know, it is still allowed to be defined as
0 (unless you also have POSIX compatibility).
With POSIX Compatibility, where NULL must have the type of (void*) you
also avoid the possible error, and thus the desire to use nullptr.
I hope that defining NULL as nullptr will become common - but I would be
surprised to ever see it being required by C standards.
The ideal would be for C libraries to define NULL as nullptr and for C
compilers to support a flag like gcc's "-Wzero-as-null-pointer-constant"
warning (it is currently C++ only).  Then people can easily eliminate
any mixup between integer 0 and null pointer constants by using that
flag and either NULL or nullptr, according to taste.  (And those who
don't want such checks, are not required to change.)
I want a compiler flag "define NULL as nullptr"
Richard Harnden
2024-07-09 05:42:30 UTC
Permalink
Post by David Brown
Post by Richard Damon
Post by Thiago Adams
If you were creating C code today and could use a C23 compiler, would
you use nullptr instead of NULL?
I am asking because I think I will keep using NULL.
I like nullptr semantics but I don't like to introduce new element
(nullptr) inside the code with no guarantee that the code will not mix both.
In the past we also didn't have a guarantee we are not mixing 0 or NULL.
I think the best scenario for a team guideline would be a style
warning if 0 or nullptr is used and NULL to be defined as nullptr in
a C23 compiler.
The (small) problem with 0 or NULL being use is that in a context
where you THINK you are passing a pointer, but the function actually
is taking an integer value, 0 or NULL (defined as a 0) passes the
syntax check.
If C23 REQURIED NULL to be defined as nullptr, then NULL would have
been used, but as far as I know, it is still allowed to be defined as
0 (unless you also have POSIX compatibility).
With POSIX Compatibility, where NULL must have the type of (void*) you
also avoid the possible error, and thus the desire to use nullptr.
I hope that defining NULL as nullptr will become common - but I would be
surprised to ever see it being required by C standards.
The ideal would be for C libraries to define NULL as nullptr and for C
compilers to support a flag like gcc's "-Wzero-as-null-pointer-constant"
warning (it is currently C++ only).  Then people can easily eliminate
any mixup between integer 0 and null pointer constants by using that
flag and either NULL or nullptr, according to taste.  (And those who
don't want such checks, are not required to change.)
So, if malloc was changed to 'returns nullptr and sets errno on error',
will you still be able to say:

if ( p == NULL ) ...
if ( !p ) ...

?
Chris M. Thomasson
2024-07-09 06:17:23 UTC
Permalink
Post by Richard Harnden
Post by David Brown
Post by Richard Damon
Post by Thiago Adams
If you were creating C code today and could use a C23 compiler,
would you use nullptr instead of NULL?
I am asking because I think I will keep using NULL.
I like nullptr semantics but I don't like to introduce new element
(nullptr) inside the code with no guarantee that the code will not mix both.
In the past we also didn't have a guarantee we are not mixing 0 or NULL.
I think the best scenario for a team guideline would be a style
warning if 0 or nullptr is used and NULL to be defined as nullptr in
a C23 compiler.
The (small) problem with 0 or NULL being use is that in a context
where you THINK you are passing a pointer, but the function actually
is taking an integer value, 0 or NULL (defined as a 0) passes the
syntax check.
If C23 REQURIED NULL to be defined as nullptr, then NULL would have
been used, but as far as I know, it is still allowed to be defined as
0 (unless you also have POSIX compatibility).
With POSIX Compatibility, where NULL must have the type of (void*)
you also avoid the possible error, and thus the desire to use nullptr.
I hope that defining NULL as nullptr will become common - but I would
be surprised to ever see it being required by C standards.
The ideal would be for C libraries to define NULL as nullptr and for C
compilers to support a flag like gcc's
"-Wzero-as-null-pointer-constant" warning (it is currently C++ only).
Then people can easily eliminate
any mixup between integer 0 and null pointer constants by using that
flag and either NULL or nullptr, according to taste.  (And those who
don't want such checks, are not required to change.)
So, if malloc was changed to 'returns nullptr and sets errno on error',
if ( p == NULL ) ...
if ( !p ) ...
?
This of a pointer p where:

p = 0;

p == NULL == true;

p == 0 == true;

Therefore (! p) means that p is 0, or NULL if you will..

Fair enough?

Side note:

Tell NULL and 0 to NAND CAT:



How long can you listen to this before you snuff it?
Richard Harnden
2024-07-09 07:02:42 UTC
Permalink
Post by Kaz Kylheku
Post by Richard Harnden
Post by David Brown
Post by Richard Damon
Post by Thiago Adams
If you were creating C code today and could use a C23 compiler,
would you use nullptr instead of NULL?
I am asking because I think I will keep using NULL.
I like nullptr semantics but I don't like to introduce new element
(nullptr) inside the code with no guarantee that the code will not mix both.
In the past we also didn't have a guarantee we are not mixing 0 or NULL.
I think the best scenario for a team guideline would be a style
warning if 0 or nullptr is used and NULL to be defined as nullptr
in a C23 compiler.
The (small) problem with 0 or NULL being use is that in a context
where you THINK you are passing a pointer, but the function actually
is taking an integer value, 0 or NULL (defined as a 0) passes the
syntax check.
If C23 REQURIED NULL to be defined as nullptr, then NULL would have
been used, but as far as I know, it is still allowed to be defined
as 0 (unless you also have POSIX compatibility).
With POSIX Compatibility, where NULL must have the type of (void*)
you also avoid the possible error, and thus the desire to use nullptr.
I hope that defining NULL as nullptr will become common - but I would
be surprised to ever see it being required by C standards.
The ideal would be for C libraries to define NULL as nullptr and for
C compilers to support a flag like gcc's
"-Wzero-as-null-pointer-constant" warning (it is currently C++ only).
Then people can easily eliminate
any mixup between integer 0 and null pointer constants by using that
flag and either NULL or nullptr, according to taste.  (And those who
don't want such checks, are not required to change.)
So, if malloc was changed to 'returns nullptr and sets errno on
if ( p == NULL ) ...
if ( !p ) ...
?
p = 0;
No, I mean when p = nullptr
Chris M. Thomasson
2024-07-09 07:12:21 UTC
Permalink
Post by Richard Harnden
Post by Kaz Kylheku
Post by Richard Harnden
Post by David Brown
Post by Richard Damon
Post by Thiago Adams
If you were creating C code today and could use a C23 compiler,
would you use nullptr instead of NULL?
I am asking because I think I will keep using NULL.
I like nullptr semantics but I don't like to introduce new element
(nullptr) inside the code with no guarantee that the code will not mix both.
In the past we also didn't have a guarantee we are not mixing 0 or NULL.
I think the best scenario for a team guideline would be a style
warning if 0 or nullptr is used and NULL to be defined as nullptr
in a C23 compiler.
The (small) problem with 0 or NULL being use is that in a context
where you THINK you are passing a pointer, but the function
actually is taking an integer value, 0 or NULL (defined as a 0)
passes the syntax check.
If C23 REQURIED NULL to be defined as nullptr, then NULL would have
been used, but as far as I know, it is still allowed to be defined
as 0 (unless you also have POSIX compatibility).
With POSIX Compatibility, where NULL must have the type of (void*)
you also avoid the possible error, and thus the desire to use nullptr.
I hope that defining NULL as nullptr will become common - but I
would be surprised to ever see it being required by C standards.
The ideal would be for C libraries to define NULL as nullptr and for
C compilers to support a flag like gcc's
"-Wzero-as-null-pointer-constant" warning (it is currently C++
only). Then people can easily eliminate
any mixup between integer 0 and null pointer constants by using that
flag and either NULL or nullptr, according to taste.  (And those who
don't want such checks, are not required to change.)
So, if malloc was changed to 'returns nullptr and sets errno on
if ( p == NULL ) ...
if ( !p ) ...
?
p = 0;
No, I mean when p = nullptr
p = nullptr;

(0 == p == nullptr == NULL == 0) == true ?

Am I missing something here? If so, here is a preemptive: Shit!
Ben Bacarisse
2024-07-09 10:14:41 UTC
Permalink
Post by Chris M. Thomasson
p = nullptr;
(p having been declared void *)
Post by Chris M. Thomasson
(0 == p == nullptr == NULL == 0) == true ?
Am I missing something here? If so, here is a preemptive: Shit!
You are missing that 0 == p == nullptr == NULL == 0 does not mean what
you want! It means

(((0 == p) == nullptr) == NULL) == 0

and that is a constraint violation.

Why? Well 0 == p has value 1 and is of type int and equality
comparisons between int and nullptr_t values (of which there is only
one) are not permitted. Catching this sort of thing is one of the
benefits of nullptr and its associated type nullptr_t. It means that
while

#define nullptr ((void *)0)

can help to get C23 code to compile with a pre-C23 compiler, it might
result in some C23 constraint violations going undetected.

Anyway, that aside, I know what you meant. To clarify, all of the
following have the value 1:

0 == p
p == nullptr
nullptr == NULL
NULL == 0
0 == nullptr
!p

Note that 0 == nullptr /is/ allowed even though 0 has type int. That is
because 0 is also a null pointer constant, and the rules for == and !=
specifically allow it.
--
Ben.
Chris M. Thomasson
2024-07-09 20:24:35 UTC
Permalink
Post by Ben Bacarisse
Post by Chris M. Thomasson
p = nullptr;
(p having been declared void *)
Post by Chris M. Thomasson
(0 == p == nullptr == NULL == 0) == true ?
Am I missing something here? If so, here is a preemptive: Shit!
You are missing that 0 == p == nullptr == NULL == 0 does not mean what
you want! It means
(((0 == p) == nullptr) == NULL) == 0
and that is a constraint violation.
Why? Well 0 == p has value 1 and is of type int and equality
comparisons between int and nullptr_t values (of which there is only
one) are not permitted. Catching this sort of thing is one of the
benefits of nullptr and its associated type nullptr_t. It means that
while
#define nullptr ((void *)0)
can help to get C23 code to compile with a pre-C23 compiler, it might
result in some C23 constraint violations going undetected.
Anyway, that aside, I know what you meant. To clarify, all of the
0 == p
p == nullptr
nullptr == NULL
NULL == 0
0 == nullptr
!p
Note that 0 == nullptr /is/ allowed even though 0 has type int. That is
because 0 is also a null pointer constant, and the rules for == and !=
specifically allow it.
It was a bit of pseudo code. Here is a program:
__________________________
#include <stdio.h>
#include <stdlib.h>

int main()
{
void* p = 0;

if ((p == NULL) && (! p))
{
printf("Good!\n");
}

else
{
printf("Strange? Humm...\n");
}

return 0;
}
__________________________

Good shall be printed even with the following condition right?
__________________________
if ((p == NULL) && (! p) && (p == nullptr))
{
printf("Good!\n");
}
__________________________

Any better Ben?
Chris M. Thomasson
2024-07-09 20:28:25 UTC
Permalink
Post by Chris M. Thomasson
Post by Ben Bacarisse
Post by Chris M. Thomasson
p = nullptr;
(p having been declared void *)
Post by Chris M. Thomasson
(0 == p == nullptr == NULL == 0) == true ?
Am I missing something here? If so, here is a preemptive: Shit!
You are missing that 0 == p == nullptr == NULL == 0 does not mean what
you want!  It means
  (((0 == p) == nullptr) == NULL) == 0
and that is a constraint violation.
Why?  Well 0 == p has value 1 and is of type int and equality
comparisons between int and nullptr_t values (of which there is only
one) are not permitted.  Catching this sort of thing is one of the
benefits of nullptr and its associated type nullptr_t.  It means that
while
#define nullptr ((void *)0)
can help to get C23 code to compile with a pre-C23 compiler, it might
result in some C23 constraint violations going undetected.
Anyway, that aside, I know what you meant.  To clarify, all of the
   0 == p
   p == nullptr
   nullptr == NULL
   NULL == 0
   0 == nullptr
   !p
Note that 0 == nullptr /is/ allowed even though 0 has type int.  That is
because 0 is also a null pointer constant, and the rules for == and !=
specifically allow it.
__________________________
#include <stdio.h>
#include <stdlib.h>
int main()
{
    void* p = 0;
    if ((p == NULL) && (! p))
    {
        printf("Good!\n");
    }
    else
    {
        printf("Strange? Humm...\n");
    }
    return 0;
}
__________________________
Good shall be printed even with the following condition right?
__________________________
if ((p == NULL) && (! p) && (p == nullptr))
{
   printf("Good!\n");
}
__________________________
Any better Ben?
To be more precise, printf shall be called if p is 0, NULL or nullptr...
They are all the same, in a sense, right?
Ben Bacarisse
2024-07-10 13:27:45 UTC
Permalink
Post by Chris M. Thomasson
Post by Chris M. Thomasson
Post by Ben Bacarisse
Post by Chris M. Thomasson
p = nullptr;
(p having been declared void *)
Post by Chris M. Thomasson
(0 == p == nullptr == NULL == 0) == true ?
Am I missing something here? If so, here is a preemptive: Shit!
You are missing that 0 == p == nullptr == NULL == 0 does not mean what
you want!  It means
  (((0 == p) == nullptr) == NULL) == 0
and that is a constraint violation.
Why?  Well 0 == p has value 1 and is of type int and equality
comparisons between int and nullptr_t values (of which there is only
one) are not permitted.  Catching this sort of thing is one of the
benefits of nullptr and its associated type nullptr_t.  It means that
while
#define nullptr ((void *)0)
can help to get C23 code to compile with a pre-C23 compiler, it might
result in some C23 constraint violations going undetected.
Anyway, that aside, I know what you meant.  To clarify, all of the
   0 == p
   p == nullptr
   nullptr == NULL
   NULL == 0
   0 == nullptr
   !p
Note that 0 == nullptr /is/ allowed even though 0 has type int.  That is
because 0 is also a null pointer constant, and the rules for == and !=
specifically allow it.
It was a bit of pseudo code.
It looked like C!
Post by Chris M. Thomasson
Post by Chris M. Thomasson
__________________________
#include <stdio.h>
#include <stdlib.h>
int main()
{
    void* p = 0;
    if ((p == NULL) && (! p))
    {
        printf("Good!\n");
    }
    else
    {
        printf("Strange? Humm...\n");
    }
    return 0;
}
__________________________
Good shall be printed even with the following condition right?
__________________________
if ((p == NULL) && (! p) && (p == nullptr))
{
   printf("Good!\n");
}
__________________________
Any better Ben?
To be more precise, printf shall be called if p is 0, NULL or
nullptr... They are all the same, in a sense, right?
In a sense, yes. If you want to know the senses in which they are not
all the same, ask some more (or read the C23 draft PDF).
--
Ben.
James Kuyper
2024-07-10 15:09:41 UTC
Permalink
"Chris M. Thomasson" <***@gmail.com> writes:
...
Post by Chris M. Thomasson
To be more precise, printf shall be called if p is 0, NULL or
nullptr... They are all the same, in a sense, right?
0 and nullptr are null pointer constants. NULL is required to expand
into a null pointer constant, but it's not required to expand into
either 0 or nullptr; it could expand into '\0' or 0ULL or ('a' - 'a'),
among an infinite variety of other possibilities. 0 and (void*)0 are the
two most likely and common choices.

Whenever they occur in a pointer context, null pointer constants get
implicitly converted to the corresponding pointer type, and the result
of that conversion is a null pointer of that type. All null pointers are
required to compare equal. In that sense, 0, NULL and nullptr are all
equivalent.

However, 0 can be used wherever an integer value is required. while
nullptr cannot, which is one of the key reasons for the existence of
nullptr. NULL can expand into an integer constant expression with a
value of 0, but it can also expand into such an expression, converted to
void*. If an implementation chooses the first option, NULL can be used
wherever an integer is allowed. If it chooses the second option, NULL
can only be used where a pointer is allowed.
Loading...