programing

C++의 NULL이 일반적으로 C와 같은 포인터가 아닌 정수 리터럴인 이유는 무엇입니까?

newstyles 2023. 11. 5. 11:03

C++의 NULL이 일반적으로 C와 같은 포인터가 아닌 정수 리터럴인 이유는 무엇입니까?

저는 C++를 수년간 써왔습니다.nullptrnull pointersnull pointers.또한 NULL이 발생하는 C를 알고 있으며, NULL 포인터에 대한 상수이며, 유형을 지정합니다.void *.

여러가지 이유로, 제가 사용할 수 밖에 없었습니다.NULL내 C++ 코드에 뭔가를 위해.템플릿 인수 추론 중에 컴파일러가 내 NULL이 정말로...라고 말할 때 내 놀라움을 상상해보세요.그래서 다시 확인해봤습니다

#include <type_traits>
#include <cstddef>

static_assert(not std::is_same<decltype(NULL), long>::value, "NULL is long ???");

그리고 실제로 정적 주장은 (GCC와 Clang과 함께) 실패합니다.

cppreference.com 에서 확인해보니 (C++11 문구):

매크로 NULL은 구현 정의 NULL 포인터 상수로, 값이 0인 정수 리터럴이거나 pr값 형식일 수 있습니다.std::nullptr_t.

이게 왜 말이 됩니까?그 자체로, 그리고 C의 비호환성에 비추어?

C에서, a.void*은연중에 임의의 것으로 변환될 수 있습니다.T*. 이와 같이 만들기NULL a void*전적으로 적절합니다.

하지만 그것은 대단히 위험합니다.따라서 C++는 이러한 변환을 제거하여 대부분의 포인터 캐스트를 수동으로 수행해야 했습니다.그러나 이는 C와 소스 호환성을 야기할 것입니다. C 프로그램은 다음을 사용한 유효한 C 프로그램입니다.NULLC가 원하는 방식은 C++에서 컴파일에 실패할 것입니다.또한 많은 중복성이 필요합니다.T *pt = (T*)(NULL);, 짜증나고 무의미할 겁니다

그래서 C++는 다시 정의했습니다.NULLmacro를 정수 리터럴 0으로 지정합니다.C에서 리터럴 0은 또한 암시적으로 임의의 포인터 유형으로 변환 가능하며 C++가 유지하는 동작인 널 포인터 값을 생성합니다.

물론 null 포인터 상수에 리터럴 0(또는 더 정확하게는 값이 0인 정수 상수 식)을 사용하는 것은...최선의 방법은 아닙니다.특히 과부하를 허용하는 언어로 말입니다.따라서 C++11은 "null 포인터 상수"를 의미하는 키워드 위에 NULL을 완전히 사용하고 다른 것은 사용하지 않았습니다.

언어 모두에서,NULL구현이 정의된 null 포인터 상수입니다.C++ 섹션 17.2.3, 이는 정의에 대해 C 7.19를 참조합니다.

그 말은 C에서NULL정수형 또는 a로 정의될 수 있습니다.void*type, 그리고 C++에서 정수 타입으로 정의될 수 있습니다; 그것은 또한 a로 정의될 수 있습니다.nullptr_t내가 표준을 정확하게 해석했다면요.숨겨진 (비규범적)각주는 다음과 같이 말합니다.(void*)0C++에는 C의 암묵적 변환이 없기 때문에 유효한 정의가 될 수 없습니다.void*다른 포인터 유형으로 이동합니다.

만약 당신이 그것을 정의하는 C 컴파일러를 가지고 있다면,((void*)0)다음과 같이 정의하는 C++ 컴파일러.0L, 둘 다 순응적입니다.두 가지 구현 모두 사용 사례를 충족합니다(할당 및 비교 가능).NULL).

C++도입nullptr주로 오버로드에 적합한 유형의 값을 제공하기 위해, 통과하는 것이 놀랍다고 여겨졌기 때문입니다.NULL함수는 정수 버전을 선택할 수 있습니다.

C는 단순히 정의하지 않습니다.NULL~하듯이(void *)0. 다음과 같이 정의할 수도 있습니다.0또는 그것을 평가하는 모든 일정한 표현.사용.#define NULL 0두 언어 중 하나로 작동합니다.

편집: 이 답변은 매우 훌륭하고 더 상세합니다.

제 가정은 항상 구현에서 지켜야 할 결정사항이었습니다.NULL~하듯이0C++98과의 하위 호환성 문제였습니다.많은 코드들을 봐왔어요NULLpointer가 아닌 컨텍스트에서 특히 배열에서 null 터미네이터(null terminator)를 대체하는 (probably적으로 의도하지 않은 또는 적어도 정보가 없는) 것입니다.2011년 이래로 가장 좋은 방법은 "사용하지 않는 것" 이었기 때문입니다.NULL아예", 재정의NULL로.nullptr좋은 코드/새로운 코드에 도움이 되는 일은 거의 하지 않으면서 나쁜 코드/오래된 코드를 깨뜨릴 수 있습니다.

vcruntime.h

다음과 같이 정의합니다.

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

언급URL : https://stackoverflow.com/questions/69057184/why-is-cs-null-typically-an-integer-literal-rather-than-a-pointer-like-in-c