Communities

Writing
Writing
Codidact Meta
Codidact Meta
The Great Outdoors
The Great Outdoors
Photography & Video
Photography & Video
Scientific Speculation
Scientific Speculation
Cooking
Cooking
Electrical Engineering
Electrical Engineering
Judaism
Judaism
Languages & Linguistics
Languages & Linguistics
Software Development
Software Development
Mathematics
Mathematics
Christianity
Christianity
Code Golf
Code Golf
Music
Music
Physics
Physics
Linux Systems
Linux Systems
Power Users
Power Users
Tabletop RPGs
Tabletop RPGs
Community Proposals
Community Proposals
tag:snake search within a tag
answers:0 unanswered questions
user:xxxx search by author id
score:0.5 posts with 0.5+ score
"snake oil" exact phrase
votes:4 posts with 4+ votes
created:<1w created < 1 week ago
post_type:xxxx type of post
Search help
Notifications
Mark all as read See all your notifications »
Q&A

Welcome to Software Development on Codidact!

Will you help us build our independent community of developers helping developers? We're small and trying to grow. We welcome questions about all aspects of software development, from design to code to QA and more. Got questions? Got answers? Got code you'd like someone to review? Please join us.

Why not call nullptr NULL?

+8
−0

In C++11 the nullptr keyword was added as a more type safe null pointer constant, since the previous common definition of NULL as 0 has some problems.

Why did the standards committee choose not to call the new null pointer constant NULL, or declare that NULL should be #defined to nullptr?

History
Why does this post require attention from curators or moderators?
You might want to add some details to your flag.
Why should this post be closed?

0 comment threads

2 answers

+5
−0

It's a long story.

Once upon a time, there were three ways to express a null pointer constant:

  • NULL
  • 0
  • ((char *) 0)

This was true at least as far back as Unix v7. Maybe even further back in time; I don't have older Unix sources at hand.

void * still didn't exist. NULL itself resolved to one of the other two.

Over time, void * was invented, and started to be used. However, it was still recent enough that it wasn't considered as written in stone. The ((char *) 0) null pointer constant started to be replaced by ((void *) 0).

Then C++ was invented, and questioned the goodness and safety of the new void *, as it could be used to circumvent type safety. C++ decided that instead of allowing 2-way conversions, it would only allow one way.

0 had been an unsafe null-pointer constant, especially in variadic function calls. And even in other places it was quite unreadable, as it could be easily confused with an integer 0. Eventually, C moved into using NULL everywhere, and defining NULL as ((void *) 0), with only residual cases of the older 0. And that use was eventually standardized into the POSIX definition of NULL, which requires that it is defined as "the value 0 cast to type void *".

However, C++ had already forked their idea of void * with distinct implicit conversions, which meant they couldn't use this better definition of NULL (it wouldn't implicitly convert to any other pointer, which is a key feature of a null pointer constant). C++ had to stick to the worst possible null pointer constants: either a literal 0, or a NULL that would itself expand to 0. In fact, most C++ code avoided using NULL (due to some irrational aversion to macros), and decided to stick with the absolute worst possible null pointer constant: 0. See https://www.stroustrup.com/bs_faq2.html#null. Ironically, in their attempt to have a safer language, they had an unsafer null pointer constant, for decades.

In the C world, almost everybody had moved to the right definition of NULL. Only a few groups had stayed with the old #define NULL 0, and only because they hadn't really reasoned about it too much. For that reason, ISO C still allowed the low-quality definition of NULL; even though mostly every vendor had the good one.

After several decades of having a broken set of null pointer constants, C++ decided to fix their self-inflicted bug. C++11 invented nullptr (and nullptr_t). C didn't care at all, because it was not a problem in C.

At some point, some people raised the false premise that C code using NULL was unsafe, because it was allowed to be defined to 0. The right thing to do would have been to follow POSIX, and require in ISO C that NULL be defined as ((void *) 0). That would have required a little bit of work, talking to those implementations that had the bad definition, and convince them to move on.

Those people didn't feel like doing that job, and had also some conflict of interest, since they were proponents of a common core between C++ and C, being (also) C++ programmers. Members of the C standard committee (WG14) proposed something that was less work: pick C++'s nullptr in C.

In the end, the feature was voted into the standard, mainly by C++ proponents, and some pressure by a few proprietary compiler vendors that didn't want to fix their broken NULL. https://thephd.dev/c23-is-coming-here-is-what-is-on-the-menu#n3042---introduce-the-nullptr-constant.

One co-author of the paper that introduced nullptr in C23, n3042, wrote the following:

Someone recently challenged me, however: they said this change is not necessary and bollocks, and we should simply force everyone to define NULL to be void*. I said that if they’d like that, then they should go to those vendors themselves and ask them to change and see how it goes. They said they would, and they’d like a list of vendors defining NULL to be 0. Problem: quite a few of them are proprietary, so here’s my Open Challenge:

if you (yes, you!!) have got a C standard library (or shim/replacement) where you define NULL to be 0 and not the void-pointer version, send me a mail and I’ll get this person in touch with you so you can duke it out with each other. If they manage to convince enough vendors/maintainers, I’ll convince the National Body I’m with to write a National Body Comment asking for nullptr to be rescinded. Of course, they’ll need to not only reach out to these people, but convince them to change their NULL from 0 to ((void*)0), which. Well.

Good luck to the person who signed up for this.

I did my work, and researched which open-source implementations were really defining NULL as 0. I could only find exactly one. I talked to them, and gave arguments of why it would be reasonable to fix their definition. https://github.com/cc65/cc65/issues/1823

Very quickly, the vendor agreed with the arguments, and changed their implementation. The co-author of the paper had to fulfill its promise, and raise a National Body Comment against its own paper, soliciting the removal of nullptr from C23. However, C++ proponents in WG14 voted in favor of ignoring the comment (not even giving reasons, other than not wanting to question again the topic), and the feature stayed in C23. https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3077.htm (search for NEN/NL5).

From the reasons that the papers that added the feature in C23 cited, let's break them down, and explain why they were invalid:

  • Compatibility with C++

    Code using NULL had always been valid C++. And C++ could #define NULL nullptr, if they really cared about C/C++ compatibility. They never cared about that, and thus never did. C++ considers C to be a misdesigned language that can only be fixed by making it be C++.

  • _Generic.

    The paper says that having nullptr be of type nullptr_t would be better for _Generic, because it would allow behaving differently for a null pointer constant input. But why should a function behave differently for a null pointer constant than for a run-time null pointer? That makes no sense at all. Also, _Generic selections would still have to take care of users passing NULL, after all, so it's just duplicating the number of branches that have to be written, making it worse.

  • Vendors refusing to fix their implementation.

    Did anybody really try? I mean, with good arguments? I have doubts. It only took me a few days to fix the only FOSS vendor that we could find. If anyone gives me the address of the maintainers of the proprietary (undisclosed) vendors that refused to do so, I'll try to convince them. Nobody gave me their addresses. I think ISO should have just told them to upgrade or die; or assume that they would not conform to C23.

History
Why does this post require attention from curators or moderators?
You might want to add some details to your flag.

0 comment threads

+0
−0

Probably just backwards compatibility with past C++ versions, where NULL = 0.

History
Why does this post require attention from curators or moderators?
You might want to add some details to your flag.

2 comment threads

C++'s NULL is broken; not C (4 comments)
However when it comes to NULL, C and C++ already differ in that C allows NULL to be defined as ((void... (1 comment)

Sign up to answer this question »