libstdc++
полагается на включение stddef.h
, которое определяет NULL
следующим образом:
// <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
Информацию о __null
можно найти в этот вопрос :
Реализация __null
является внутренней G ++. По сути, внутренний делает то, что вы наивно ожидаете от reinterpret_cast<void *>(0)
.
Его тип - 'magi c', в зависимости от контекста. По этой причине G ++ пришлось реализовать его как внутренний. Ни один обычный тип не обеспечивает точно правильную семантику. Он действует примерно как void *
, но не совсем точно.
libc++
делает примерно то же самое :
// <cstddef>
//
// Don't include our own <stddef.h>; we don't want to declare ::nullptr_t.
#include_next <stddef.h>
#include <__nullptr>
Microsoft STL
также полагается на включение stddef.h
:
#pragma once
#ifndef _CSTDDEF_
#define _CSTDDEF_
#include <yvals_core.h>
#if _STL_COMPILER_PREPROCESSOR
#include <stddef.h>
Я не смог найти stddef.h
в репозитории STL с открытым исходным кодом, но определение NULL
предоставляется в vcruntime.h
:
#ifndef NULL
#ifdef __cplusplus
#define NULL 0
#else
#define NULL ((void *)0)
#endif
#endif
Простой тест на icc 19.0.1
также показывает, что NULL
не определяется как 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, "");
в прямом эфире на godbolt.org