Search code examples
c++c++11nullstdnullptr

Does any major C++ implementation actually define `NULL` as `nullptr`?


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?


Solution

  • 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