3

Since C++11, the Standard allows the macro NULL to either be a integer literal with value zero, or a prvalue of type std::nullptr_t.

Any Standard Library vendor deciding to change their definition of NULL from an integer to nullptr would very likely cause breakage for clients relying on pre-C++11 code.

Does any major implementation (e.g. GCC, Clang, MSVC) actually define NULL as nullptr? Or, despite the possibility, does nobody do this?

Vittorio Romeo
  • 90,666
  • 33
  • 258
  • 416
  • 3
    You can trivially determine this for your toolchain (indeed, for all three). Are you experiencing some practical problem with obtaining this information? – Asteroids With Wings May 09 '20 at 16:11
  • Also, why does it matter? – Asteroids With Wings May 09 '20 at 16:12
  • @AsteroidsWithWings: no, I figured that it would be more valuable to have the information publicly available as a StackOverflow question, which can be found from people with the same curiosity in the future without requiring duplicated work. I also figured that there might be some "non-major" implementation that I am not aware of which might do something different, and someone might want to share their information on that. – Vittorio Romeo May 09 '20 at 16:13
  • @AsteroidsWithWings: you're also assuming that I am not doing the research as we speak (I am), but I preferred writing the question first to see if somebody had already done the work. If nobody replies, I will self-answer. – Vittorio Romeo May 09 '20 at 16:15
  • I think there is a certain subjectivity in what folks may consider a 'major implementation'. – Adrian Mole May 09 '20 at 16:16
  • I see. Perhaps we have different definitions of the word "valuable". :) – Asteroids With Wings May 09 '20 at 16:17
  • 5
    If changing `NULL` from `0L` to `nullptr` breaks your code, your code has always been broken imho. – Aykhan Hagverdili May 09 '20 at 16:17
  • @Ayxan Not when the definition is shared with C implementations, as it almost always is. I can think of very little reason any project would want to go to the trouble of making `NULL` mean `nullptr` in C++. – Asteroids With Wings May 09 '20 at 16:17
  • @AsteroidsWithWings: do you know a case where it isn't shared with C implementations? I am interested in that. – Vittorio Romeo May 09 '20 at 16:18
  • @VittorioRomeo I do not - by saying "almost" I was just hedging my bets ;) – Asteroids With Wings May 09 '20 at 16:18
  • @Ayxan For what it's worth, "your code was broken anyway" might be true in principle, but in practice implementers will still try not to cause headaches for no good reason, no matter whose "fault" it is. – Asteroids With Wings May 09 '20 at 16:19
  • 1
    @AsteroidsWithWings what do you mean by "Shared with C"? It's usually `0L` for C++ and `(void*)0` for C with `#ifndef __cplusplus`. – Aykhan Hagverdili May 09 '20 at 16:19
  • 1
    @Ayxan Ah, really? Did not know that. – Asteroids With Wings May 09 '20 at 16:20
  • Regardless, this has turned into a discussion without revealing why this information is valuable or why it should be sought in an SO question. – Asteroids With Wings May 09 '20 at 16:20
  • @AsteroidsWithWings: are curiosities about a language explicitly disallowed on SO? If you want some *"value"*, then knowing whether my C++03 code with improper usage of `NULL` will work on any major implementation is indeed valuable if I am thinking of migrating. – Vittorio Romeo May 09 '20 at 16:21
  • @AsteroidsWithWings: a more *valuable* use of your time would be not interacting with a question you're not interested in, but do not assume that everybody feels the same way. – Vittorio Romeo May 09 '20 at 16:22
  • 1
    @Asteroids - Major implementations already went to the trouble of differentiating `NULL` between C and C++ in the past (`(void*)0` in C vs just `0` in C++). It isn't a stretch. – StoryTeller - Unslander Monica May 09 '20 at 16:22
  • @StoryTeller-UnslanderMonica Do the reasons they went to that trouble apply to this hypothetical too? I am getting the impression that they "had to" make the prior distinction, whereas there's no good reason to make a change here now? – Asteroids With Wings May 09 '20 at 16:32
  • 1
    @Asteroids - Obtaining a synonym for a valid null pointer constant that is as least error prone as possible? Certainly. Otherwise a plain 0 would have sufficed for C as well. – StoryTeller - Unslander Monica May 09 '20 at 16:33
  • 3
    For reference, STL had an anecdote about trying to change this and running into a bunch of problems within their own code: https://youtu.be/AKtHxKJRwp4?t=3437. OTOH, there was [this tweet](https://twitter.com/stephantlavavej/status/1000548957171273728) some years later, same person. – chris May 09 '20 at 16:40

1 Answers1

4

libstdc++ relies on including stddef.h, which defines NULL in the following way:

// <stddef.h>
//
#if defined (_STDDEF_H) || defined (__need_NULL)
#undef NULL     /* in case <stdio.h> has defined it. */
#ifdef __GNUG__
#define NULL __null
#else   /* G++ */
#ifndef __cplusplus
#define NULL ((void *)0)
#else   /* C++ */
#define NULL 0
#endif  /* C++ */
#endif  /* G++ */
#endif  /* NULL not defined and <stddef.h> or need NULL.  */
#undef  __need_NULL

Information about __null can be found in this question:

The implementation of __null is as a G++ internal. Basically, the internal does what you would naively expect reinterpret_cast<void *>(0) to do.

Its type is 'magic', depending on context. That's the reason G++ had to implement it as an internal. No regular type provides the precisely-correct semantics. It acts roughly like void *, but not exactly.


libc++ does pretty much the same thing:

// <cstddef>
//
// Don't include our own <stddef.h>; we don't want to declare ::nullptr_t.
#include_next <stddef.h>
#include <__nullptr>

Microsoft's STL also relies on including stddef.h:

#pragma once
#ifndef _CSTDDEF_
#define _CSTDDEF_
#include <yvals_core.h>
#if _STL_COMPILER_PREPROCESSOR

#include <stddef.h>

I could not find stddef.h in the open-source STL repository, but a definition of NULL is provided in vcruntime.h:

#ifndef NULL
    #ifdef __cplusplus
        #define NULL 0
    #else
        #define NULL ((void *)0)
    #endif
#endif

A simple test on icc 19.0.1 also shows that NULL is not defined as nullptr:

#include <type_traits>
#include <cstddef>

static_assert(!std::is_same<decltype(NULL), std::nullptr_t>::value, "");
static_assert(!std::is_same<decltype(NULL), int>::value, "");
static_assert(std::is_same<decltype(NULL), long>::value, "");

live on godbolt.org

Vittorio Romeo
  • 90,666
  • 33
  • 258
  • 416