NULL versus 0

69 views
Skip to first unread message

das...@gmail.com

unread,
Sep 25, 2021, 2:03:40 PMSep 25
to
I'm reading "Sams Teach Yourself C++ in One Hour a Day (6th Edition)".

(I'm already an expert-level C programmer, learning C++. I just say that as notice that you don't need to overexplain.)

In the examples in the book, they assign pointers to 0, typically at definition, i.e.

int *pInt = 0;

Nothing inherently wrong with that, but in C, it would be more traditional to use NULL. I believe the value assigned is going to be the same, whether 0 or NULL is used.

Is one style preferred over the other in C++? Why?

Thanks.

Branimir Maksimovic

unread,
Sep 25, 2021, 2:16:10 PMSep 25
to
There were problems between using 0 as *integer* or *pointer*, now
we have nullptr to differentitate.

> Thanks.
>


--

7-77-777
Evil Sinner!

Paavo Helde

unread,
Sep 25, 2021, 2:20:10 PMSep 25
to
In C++ (unlike C), NULL is a macro defined to 0, so there is no
difference. There are special rules about converting literal 0 to
pointer values. However, this was a kind of hack which did not work so
well after all, so C++11 introduced a new special keyword for a null
pointer. So the current preferred style is:

int *pInt = nullptr;

Paavo Helde

unread,
Sep 25, 2021, 2:32:42 PMSep 25
to
25.09.2021 21:20 Paavo Helde kirjutas:
> 25.09.2021 21:03 das...@gmail.com kirjutas:
>> I'm reading "Sams Teach Yourself C++ in One Hour a Day (6th Edition)".
>>
>> (I'm already an expert-level C programmer, learning C++.  I just say
>> that as notice that you don't need to overexplain.)
>>
>> In the examples in the book, they assign pointers to 0,

Oh, and if this book predates C++11 (i.e. 2011), be aware that some
content is out-dated and it does not cover the myriad of new
enhancements introduced by C++11. You might want to use a newer book.

C++11 is quite essential for using C++ effectively nowadays. Later
additions have been smaller and more specialized, so can be postponed
for a while.

das...@gmail.com

unread,
Sep 25, 2021, 3:08:24 PMSep 25
to
> Oh, and if this book predates C++11 (i.e. 2011), be aware that some
> content is out-dated and it does not cover the myriad of new
> enhancements introduced by C++11. You might want to use a newer book.
>
> C++11 is quite essential for using C++ effectively nowadays. Later
> additions have been smaller and more specialized, so can be postponed
> for a while.

Thanks for the heads up! You were correct. Amazon tells me that the 6th edition was released in 2008, and I purchased it in 2011. (It seems like only yesterday LOL.)

I spent $20.49 and grabbed the latest edition (8th edition), which claims to cover C++ 2011 and C++ 2014. Since I'm only in Chapter 8, re-skimming for changes should be easy and then I can continue.

TBH, it would not have made a practical difference. I'm actually working on a Blackjack simulation program (and writing a book) to evaluate card counting strategies, so that I can drink and gamble more. I figured it would be a good chance to learn and get comfortable with C++ (although I could do it in C). For that type of program (mildly complex simulation, essentially numerical), advanced features of the language probably would not come into play.

As an aside, SOMEBODY will point out that there are lots of Blackjack books on the market, and what more could I want to know. Just to satisfy the curious, here are my reasons:

a)Blackjack authors are, on average, bad mathematicians. I don't trust what they publish. I would prefer to double-check.

b)I would prefer to know the first decimal point after some true count boundaries. For example, with hi-lo, it is typical to take the insurance bet at 3 or above. Is it really 3? Or is it 3.2? I can do arithmetic in my head well enough to want to know precisely.

c)No book I'm aware of covers the mathematical basis of camouflage plays (and it is mathematical). The goal is to do something that appears as bizarre as possible but that has a very small negative impact on expected value, so as to keep the dealer and pit bosses convinced that you aren't right in the head rather than being a skilled card counter. The notion of what you can do that appears bizarre but is not costly is mathematical.

d)I would like to maximize total return, which also involves counting against side bets, if possible. So, the "best" counting strategy at a given game with side bets may not be the best strategy for pure Blackjack. Again, no book I'm aware of looks at how best to count against the TOTAL game, including side bets.

So, to cut off the obvious feedback I would otherwise receive, .... no, I'm not reinventing the wheel.

Thanks for the heads up on upgrading my book!

see.my....@gmail.com

unread,
Sep 25, 2021, 4:06:01 PMSep 25
to
> int *pInt = 0;
>
> Nothing inherently wrong with that, but in C, it would be more traditional to use NULL.

It would be more traditional in C++, as well. Even though the actual definition means it's the same for the compiler, there is a difference for the human reader. NULL stands out in the code and immediately draws attention to its intended meaning as a pointer, whereas literal 0 is a number. I certainly prefer NULL over 0 in such uses.

> Is one style preferred over the other in C++? Why?

Things get more interesting with nullptr vs. NULL (since C++11), but I have to admit I'm not much excited about nullptr. NULL still draws attention more and I appreciate it for exactly this reason. Does it cause problems? I don't deny any horror story, but I certainly don't have any to share myself, so nullptr did not solve any measurable problem for me. I still write NULL in new code (and that usually applies to calling 3rd-party libraries) and I don't feel bad about it. You might find convincing arguments for the contrary, too. I believe it will stay as subjective choice forever.

--
Maciej Sobczak * http://www.inspirel.com

James Kuyper

unread,
Sep 25, 2021, 5:36:37 PMSep 25
to
In C, NULL can be defined as (void*)0, which is safer than 0, because it
cannot be accidentally used in arithmetic contexts, which is a good
reason to prefer NULL.

In C++, NULL is not permitted to expand to (void*)0, but it can be
defined as nullptr, which is not only safer than 0, but also is safer
than (void*)0, so NULL should be preferred in C++, too. However, as a
general rule explicit use of nullptr would be even better, because NULL
could simply be defined as 0.

Jorgen Grahn

unread,
Sep 26, 2021, 2:58:26 AMSep 26
to
On Sat, 2021-09-25, see.my....@gmail.com wrote:
>> int *pInt = 0;
>>
>> Nothing inherently wrong with that, but in C, it would be more
>> traditional to use NULL.
>
> It would be more traditional in C++, as well.

Opinions varied. Before nullptr, I always used NULL in C and 0 in
C++. IIRC using 0 was a common recommendation here, too, for whatever
reason.

/Jorgen

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

Branimir Maksimovic

unread,
Sep 26, 2021, 3:47:28 AMSep 26
to
On 2021-09-26, Jorgen Grahn <grahn...@snipabacken.se> wrote:
> On Sat, 2021-09-25, see.my....@gmail.com wrote:
>>> int *pInt = 0;
>>>
>>> Nothing inherently wrong with that, but in C, it would be more
>>> traditional to use NULL.
>>
>> It would be more traditional in C++, as well.
>
> Opinions varied. Before nullptr, I always used NULL in C and 0 in
> C++. IIRC using 0 was a common recommendation here, too, for whatever
> reason.

#define NULL (void*)0
simple, problem is that in C++, one have to cast from void
and that does not works, and this is BuG in C++.


--

7-77-777
Evil Sinner!

Keith Thompson

unread,
Sep 26, 2021, 5:15:25 AMSep 26
to
That's not a valid definition of NULL in either C or C++.

In C or C++, the definition has to be parenthesized to avoid parsing
errors in some contexts;

#define NULL ((void*0)

I'm not sure what you mean by "this is BuG in C++". A C++
implementation that defined NULL that way would be non-conforming.

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

Keith Thompson

unread,
Sep 26, 2021, 5:17:25 AMSep 26
to
Jorgen Grahn <grahn...@snipabacken.se> writes:
> On Sat, 2021-09-25, see.my....@gmail.com wrote:
>>> int *pInt = 0;
>>>
>>> Nothing inherently wrong with that, but in C, it would be more
>>> traditional to use NULL.
>>
>> It would be more traditional in C++, as well.
>
> Opinions varied. Before nullptr, I always used NULL in C and 0 in
> C++. IIRC using 0 was a common recommendation here, too, for whatever
> reason.

As I recall, Stroustrup's books used 0 when a null pointer constant was
required, and that was probably the origin of the (pre-nullptr)
convention to use 0 in C++ while NULL is more widely recommended in C.

Branimir Maksimovic

unread,
Sep 26, 2021, 5:38:43 AMSep 26
to
On 2021-09-26, Keith Thompson <Keith.S.T...@gmail.com> wrote:
>>
>> #define NULL (void*)0
>> simple, problem is that in C++, one have to cast from void
>> and that does not works, and this is BuG in C++.
>
> That's not a valid definition of NULL in either C or C++.
>
> In C or C++, the definition has to be parenthesized to avoid parsing
> errors in some contexts;
>
> #define NULL ((void*0)
>
> I'm not sure what you mean by "this is BuG in C++". A C++
> implementation that defined NULL that way would be non-conforming.
>
Exactly, that is why it is Bug.
Thanks for correction, BTW.

--

7-77-777
Evil Sinner!

Bo Persson

unread,
Sep 26, 2021, 7:54:45 AMSep 26
to
It is not a bug when it is done very much on purpose.

Stroustrup says:

"A pointer to any type of object can be assigned to a variable of type
void*, a void* can be assigned to another void*, void* can be compared
for equality and inequality, and a void* can be explicitly converted to
another type. Other operations would be unsafe because the compiler
cannot know what kind of object is really pointed to. Consequently,
other operations result in compile-time errors."


Horsey...@the_stables.com

unread,
Sep 26, 2021, 10:20:45 AMSep 26
to
On 26 Sep 2021 06:58:15 GMT
Jorgen Grahn <grahn...@snipabacken.se> wrote:
>On Sat, 2021-09-25, see.my....@gmail.com wrote:
>>> int *pInt = 0;
>>>
>>> Nothing inherently wrong with that, but in C, it would be more
>>> traditional to use NULL.
>>
>> It would be more traditional in C++, as well.
>
>Opinions varied. Before nullptr, I always used NULL in C and 0 in
>C++. IIRC using 0 was a common recommendation here, too, for whatever
>reason.

It still use NULL instead of nullptr because its a lot more obvious when
speed reading code.

Keith Thompson

unread,
Sep 26, 2021, 6:03:53 PMSep 26
to
To be clear, you're saying that if any C++ implementation actually
defined NULL that way, it would be a bug in that implementation.
That's true, but I'm not aware of any implementation that actually
has that hypothetical bug. It can require some trivial extra work
for an implementation that shares headers between C and C++, but
implementers are well aware of the issue.

Keith Thompson

unread,
Sep 26, 2021, 6:17:31 PMSep 26
to
"The C++ Programming Language", 4th edition, section 7.2.1.

As Stroustrup says, converting from void* to another pointer type
requires an explicit conversion, but converting NULL to any pointer
type does not. (void*)0 is a null pointer constant in C, but not in C++.

This:
int *p;
p = (void*)0;
is invalid in C++, but this:
int *p;
p = NULL;
is valid. Because of that, a C++ implementation that defines NULL as
either (void*)0 or ((void*)0) is non-conforming. (It's unlikely that
any actual C++ implementations make that mistake.)

Juha Nieminen

unread,
Sep 27, 2021, 1:47:12 AMSep 27
to
Paavo Helde <myfir...@osa.pri.ee> wrote:
> In C++ (unlike C), NULL is a macro defined to 0, so there is no
> difference.

Actually, many standard library implementations define NULL to be
nullptr (if we are in C++11 or newer).

(I haven't checked the standard, but this tells me that the standard does
not mandate NULL to be defined as 0.)

Chris M. Thomasson

unread,
Sep 27, 2021, 2:05:28 AMSep 27
to
void* foo = 0;
void* foobar = NULL;
void* foobarCpp = nullptr;

Means foo == foobar == foobarCpp.

So, they should all be the same. Well, an impl can define these things
to mean a "null" pointer on their system, so to speak. Magic! nullptr
might mean something odd, and exotic under the hood... So does 0 wrt
pointers... ;^)

_____________________________
#include <iostream>

int main()
{
void* foo = 0;
void* foobar = NULL;
void* foobarCpp = nullptr;

std::cout << "foo = " << foo << "\n";
std::cout << "foobar = " << foobar << "\n";
std::cout << "foobarCpp = " << foobarCpp << "\n";

return 0;
}
_____________________________

Well, shit... Whats your output?
Can you even compile the damn thing?

;^)

Bo Persson

unread,
Sep 27, 2021, 2:32:49 AMSep 27
to
It just says

"The macro NULL is an implementation-defined null pointer constant."

And then a footnote saying that 0 is one possibility, but (void*)0 is not.

Chris M. Thomasson

unread,
Sep 27, 2021, 2:37:30 AMSep 27
to

Alf P. Steinbach

unread,
Sep 27, 2021, 4:32:56 AMSep 27
to
C++17 §7.11/1:
❝A /null pointer constant/ is an integer literal with value zero or a
prvalue of type `std::nullptr_t`.❞

As I recall the insistence on a null pointer constant being a literal
was introduced in C++11; the C++03 definition was

C++03 §4.10/1:
❝A /null pointer constant/ is an integral constant expression rvalue of
integer type that evaluates to zero.❞

A subtle but perhaps important change.


- Alf

Keith Thompson

unread,
Sep 27, 2021, 2:32:57 PMSep 27
to
Perhaps subtle, but I don't think it's all that important. It means
that (2-2) is a null pointer constant in C++03 but not in C++17 -- but I
can't think of any good reason to use (2-2) as a null pointer constant
outside of deliberately contrived code.

Of course the addition of `std::nullptr_t` is important.

James Kuyper

unread,
Sep 27, 2021, 3:03:31 PMSep 27
to
The mandate is quite clear:

"The macro NULL is an implementation-defined null pointer constant."
(17.2p3).

Note that "null pointer constant" has a different definition in C++ than
in C, and when compiling using C++, NULL must have a definition that
meets C++ requirements rather than C requirements. In particular, that
means that NULL can expand to "a prvalue of type std::nullptr_t." (7.3.11p1)

Branimir Maksimovic

unread,
Sep 28, 2021, 10:27:16 PMSep 28
to
Problem is that you can convert to unknown type, but compiler doesn't
just converto to enyother type. This is simply pointless as compiler
cannot possibly know what is unknown type, cast or not :P
Let's take *any* implicit conversion then, like new languages DO :P


--

7-77-777
Evil Sinner!

Branimir Maksimovic

unread,
Sep 28, 2021, 10:29:17 PMSep 28
to
On 2021-09-26, Keith Thompson <Keith.S.T...@gmail.com> wrote:
> Branimir Maksimovic <branimir....@gmail.com> writes:
>> On 2021-09-26, Keith Thompson <Keith.S.T...@gmail.com> wrote:
>>>> #define NULL (void*)0
>>>> simple, problem is that in C++, one have to cast from void
>>>> and that does not works, and this is BuG in C++.
>>>
>>> That's not a valid definition of NULL in either C or C++.
>>>
>>> In C or C++, the definition has to be parenthesized to avoid parsing
>>> errors in some contexts;
>>>
>>> #define NULL ((void*0)
>>>
>>> I'm not sure what you mean by "this is BuG in C++". A C++
>>> implementation that defined NULL that way would be non-conforming.
>>>
>> Exactly, that is why it is Bug.
>> Thanks for correction, BTW.
>
> To be clear, you're saying that if any C++ implementation actually
> defined NULL that way, it would be a bug in that implementation.
> That's true, but I'm not aware of any implementation that actually
> has that hypothetical bug. It can require some trivial extra work
> for an implementation that shares headers between C and C++, but
> implementers are well aware of the issue.
>
We have problem off overoading resolution then with constant zero.
Still, despite nullptr. You can accidentally mean 0 the integer
and have overload with pointer argument, and hav COMPILER BUG.
This should be corrected in future standard...

--

7-77-777
Evil Sinner!

Keith Thompson

unread,
Sep 28, 2021, 11:35:08 PMSep 28
to
I don't know what "COMPILER BUG" you're talking about.

Using 0 as a null pointer constant in the presence of overloaded
functions can lead to a *programming* bug. I'm not aware of any C++
compiler that has a bug in this area (i.e., handles it in a way that's
inconsistent with what the language requires).

That kind of programming bug can be avoided by using nullptr rather than
0 (something that wasn't possible before C++11).

If you're suggesting changing the language so that 0 is no longer a null
pointer constant, that would break tons of existing code.

Programming bugs, compiler bugs, and language bugs are three very
different things.

David Brown

unread,
Sep 29, 2021, 2:52:55 AMSep 29
to
Yes. But if you want that effect, some compilers will give you it with
the right flags (-Werror=zero-as-null-pointer-constant in gcc).

The downside of backwards compatibility in C and C++ is that it is hard
to remove features, even if they have been shown to be dangerous or
replaced by significantly better alternatives. Look how long it has
taken C to get rid of non-prototype function declarations - 33 years,
assuming C23 comes out on plan.

It would be nice if there were some way to standardise options like this
in a cross-compiler fashion (perhaps with pragmas rather than compiler
flags, so that they are included in the source code). The C++ and C
committees [[attributes]] to standardise common extensions (gcc/clang
__attribute__, MSVC declspec). So I live in hope!
Reply all
Reply to author
Forward
0 new messages