Действительно ли какая-либо основная реализация C ++ определяет `NULL` как` nullptr`? - PullRequest
3 голосов
/ 09 мая 2020

Начиная с C ++ 11, Стандарт позволяет макросу NULL быть либо целочисленным литералом с нулевым значением, либо prvalue типа std::nullptr_t.

Любой поставщик стандартной библиотеки, решивший изменить свое определение NULL с целого числа на nullptr, скорее всего, вызовет поломку у клиентов, полагающихся на код до C ++ 11.

Определяет ли какая-либо основная реализация (например, G CC, Clang, MSV C) NULL как nullptr? Или, несмотря на возможность, этого никто не делает ?

1 Ответ

4 голосов
/ 09 мая 2020

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

...