programing

포인터가 NULL 포인터인지 확인하려면 어떻게 해야 하나요?

kingscode 2022. 8. 11. 18:41
반응형

포인터가 NULL 포인터인지 확인하려면 어떻게 해야 하나요?

나는 항상 단순하게 생각한다.if(p != NULL){..}그 일을 할 수 있을 거야그러나 이 Stack Overflow 질문을 읽어본 결과 그렇지 않은 것 같습니다.

그러면 NULL 포인터가 0이 아닌 값을 가질 수 있다는 질문의 모든 논의를 흡수하고 NULL 포인터를 확인하는 표준 방법은 무엇일까요?

저는 항상 단순하게 if(p!=NULL){..}이(가) 작업을 수행합니다.

그것은 그럴거다.

우선, 100% 명확하게 하기 위해서, 여기에서는 C와 C++의 차이는 없습니다.둘째, 당신이 인용한 스택 오버플로우 질문은 늘 포인터에 대해 말하는 것이 아닙니다.그것은 무효 포인터를 도입하고 있습니다.최소한 표준에 관한 한, 그것들을 비교하려고 하는 것만으로 정의되지 않은 동작을 일으키는 포인터입니다.일반적으로 포인터가 유효한지 테스트할 방법은 없습니다.

마지막으로 늘 포인터를 확인하는 방법은 세 가지가 있습니다.

if ( p != NULL ) ...

if ( p != 0 ) ...

if ( p ) ...

기계상의 늘 포인터의 표현에 관계없이 모두 동작합니다.어떤 식으로든 오해의 소지가 있습니다.어떤 것을 선택하느냐가 가장 덜 나쁜 것을 선택하는 문제입니다.형식적으로 첫 번째 두 개는 컴파일러의 들여쓰기입니다.상수NULL또는0의 유형의 늘 포인터로 변환됩니다.p변환 결과는 다음과 같습니다.p. 늘 포인터의 표현에 관계없이.

세 번째는 약간 다릅니다.p암묵적으로 변환되다bool그러나 암묵적인 변환은 그 결과로서 정의된다.p != 0같은 결과가 됩니다.(즉, 3번째 스타일을 사용하는 것은 유효한 논거가 없다는 것입니다.암묵적인 변환에 의해 애매모호해지기 때문에 이점을 상쇄할 수 없습니다.)

당신이 처음 두 개 중 어느 것을 선호하느냐는 주로 스타일의 문제이며, 아마도 다른 곳에서 당신의 프로그래밍 스타일에 의해 부분적으로 결정될 것이다: 관련된 관용어에 따라, 거짓말 중 하나가 다른 것보다 더 성가시게 될 것이다.비교의 문제라면, 대부분의 사람들은 이 문제에 대해NULL단, 다음과 같은 방법으로f( NULL )선택되는 과부하는f( int )포인터로 과부하가 되지 않도록 합니다.마찬가지로 만약f함수 템플릿입니다.f( NULL )에서 템플릿을 인스턴스화합니다.int(물론 g++와 같은 일부 컴파일러는 다음과 같은 경우 경고를 생성합니다.NULLg++ 를 사용하는 경우는, 를 정말로 사용할 필요가 있습니다.NULL.)

물론 C++11에서는 다음 용어가 선호됩니다.

if ( p != nullptr ) ...

다른 솔루션의 대부분의 문제를 회피합니다(단, C와 호환되지 않습니다).

if(p != NULL)는 포인터가 NULL인지 여부를 확인하는 안전하고 휴대용 방법입니다.

C11 표준의 섹션 7.19는 stdef.h에 포함된 정의를 다음과 같이 기술한다.NULL관련 부품은 다음과 같습니다.

1 헤더<stddef.h>는 다음 매크로를 정의하고 다음 유형을 선언합니다.일부는 각각의 하위 절에서 설명한 것처럼 다른 머리글에도 정의되어 있다.

...

3 매크로는

NULL

이 값은 구현 정의 늘 포인터 상수로 확장됩니다.

이것만 기재되어 있습니다.NULL구현이 정의되어 있습니다.모든 비트 0을 가질 필요는 없습니다.

또한 섹션 6.2.3.2p3에서는 늘 포인터와 늘 포인터 상수를 정의하고 있습니다.

값이 0인 정수 상수 표현식 또는 형식으로 캐스트된 표현식void *는 늘 포인터 상수라고 불립니다.늘 포인터 상수가 포인터 타입으로 변환되면 포인터라고 불리는 결과 포인터는 오브젝트 또는 함수에 대한 포인터와 동등하지 않음을 보증합니다.

위의 내용은 다음과 같습니다.0(포인터로 변환된 경우) 및(void *)0는 늘 포인터 상수를 구성하며, 결과 포인터가 모든 비트0을 갖는다는 의미는 아닙니다.한 유형에서 다른 유형으로 값을 변환한다고 해서 반드시 표현이 동일하다고는 할 수 없는 다른 예가 이 표준에는 몇 가지 있습니다.

또한 Null 포인터 상수는 객체 또는 함수와 비교가 되지 않음을 나타냅니다.이 섹션의 단락 4에도 다음과 같이 기술되어 있다.

null 포인터를 다른 포인터 유형으로 변환하면 해당 유형의 null 포인터가 생성됩니다.임의의 두 개의 늘 포인터는 동등하게 비교해야 한다.

그래서 만약에p는 늘 포인터입니다.다음과 같은 늘 포인터와 비교해야 합니다.NULL이 경우p != NULLfalse로 평가됩니다.반대로 만약p오브젝트 또는 함수를 가리키면 그 포인터는 어떤 늘 포인터와도 동등하지 않아야 합니다.p != NULL사실로 평가될 것입니다.

여기서도 null 포인터의 표현에 대해 가정하는 것은 없습니다.

당신이 언급하는 실마찬가지로C++.

C스니펫은 항상 작동합니다.심플한 것이 좋다if (p) { /* ... */ }.

C의 모든 비교는 표현이 아닌 값으로 이루어지기 때문에 포인터의 표현은 비교와 무관합니다.표현을 비교할 수 있는 유일한 방법은 다음과 같은 끔찍한 것입니다.

static const char ptr_rep[sizeof ptr] = { 0 };
if (!memcmp(&ptr, ptr_rep, sizeof ptr)) ...

음, 이 질문은 2011년 이전에 질문되고 대답되었습니다. 하지만 거기에는nullptrC++11로 설정합니다.지금은 그것만 쓰고 있어요.

자세한 내용은 Stack Overflow 및 이 문서를 참조하십시오.

컴파일러는 일관된 유형의 시스템을 제공하고 표준 변환 세트를 제공해야 합니다.정수 값 0이나 NULL 포인터는 모두 0비트로 나타낼 필요는 없지만 컴파일러는 입력 파일의 "0" 토큰을 정수 0에 대한 올바른 표현으로 변환해야 하며 캐스트에서 포인터 형식으로 변환해야 합니다.

이것의 의미는

void *p;
memset(&p, 0, sizeof p);
if(p) { ... }

여기서 비트 패턴을 상정하고 있기 때문에, 모든 타겟시스템에서 동일하게 동작하는 것은 보증되지 않습니다.

예를 들어 메모리 보호를 하지 않고 인터럽트 벡터를 주소 0으로 유지하는 임베디드 플랫폼이 있습니다.따라서 관례상 정수 및 포인터는 변환 시 0x2000000으로 XOR 처리되며 (void *)0은 참조되지 않을 때 버스 오류를 발생시키는 주소를 가리키지만 포인터를 사용하여 테스트합니다.if스테이트먼트를 지정하면 먼저 정수 표현으로 반환되며, 그 후 모두 변환됩니다.

여기서 null 포인터의 실제 표현은 관련이 없습니다.값이 0인 정수 리터럴(포함)0및 의 유효한 정의NULL)는 어떤 포인터 타입으로 변환할 수 있으며, 실제 표현에 관계없이 늘 포인터를 제공합니다.그렇게p != NULL,p != 0그리고.p는 모두 비점수 포인터에 대한 유효한 테스트입니다.

다음과 같이 꼬인 내용을 쓴 경우 null 포인터가 0이 아닌 표현에 문제가 발생할 수 있습니다.p != reinterpret_cast<void*>(0)그러니 그러지 마세요.

방금 당신의 질문이 C++와 마찬가지로 C 태그로 되어 있는 것을 알게 되었습니다.제 대답은 C++이고 다른 언어들은 다를 수 있습니다.당신은 어떤 언어를 사용하고 있습니까?

ReferenceURL : https://stackoverflow.com/questions/6185821/how-do-we-check-if-a-pointer-is-null-pointer

반응형