>  기사  >  백엔드 개발  >  C에서 널 포인터를 사용하여 정적 멤버에 액세스하는 것이 허용되는 이유는 무엇입니까?

C에서 널 포인터를 사용하여 정적 멤버에 액세스하는 것이 허용되는 이유는 무엇입니까?

Susan Sarandon
Susan Sarandon원래의
2024-11-03 01:33:02884검색

Why is it allowed to access static members using a null pointer in C  ?

C에서 Null 포인터를 사용하여 정적 멤버에 액세스

Context

다음 프로그램을 고려하세요.

<code class="cpp">#include <iostream>
class Demo
{
public:
    static void func() { std::cout << "func() called" << std::endl; }
    static int num = 9;
};

int main()
{
    Demo* d = nullptr;
    d->func();
    std::cout << d->num << std::endl;
    return 0;
}

질문

이 프로그램은 오류 없이 컴파일되고 실행되지만, 널 포인터를 통해 정적 멤버에 액세스하는 것은 일반적으로 정의되지 않은 동작으로 간주됩니다. 이것이 허용되는 이유는 무엇입니까?

대답

TL;DR:

널 포인터를 통한 간접 참조가 허용되지 않기 때문에 해당 프로그램은 정의되지 않은 동작을 트리거하지 않습니다. 유효한 개체 ID에 의존하는 추가 작업이 포함되지 않는 한 본질적으로 문제가 있습니다.

설명:

널 포인터를 통한 간접 참조가 본질적으로 정의되지 않은 동작인지 여부는 논쟁의 여지가 있었습니다. . 프로그램에서 유일하게 의심스러운 작업은 d->a 표현식의 평가입니다.

d->a는 포인터 역참조 규칙으로 인해 (*d).a와 동일합니다. 그러나 *d가 정의되지 않은 경우에도 *d 표현식은 계속 평가됩니다. 특히 d->a의 경우처럼 결과가 삭제될 때 더욱 그렇습니다. 이 동작은 잘 정의되어 있습니다.

정적 멤버의 동작은 null 포인터를 통해 비정적 멤버에 액세스하는 것과 다릅니다. 이는 잘못된 개체 ID를 의미하므로 실제로 정의되지 않은 동작을 트리거해야 합니다. 반면에 정적 멤버에 액세스하려면 개체 ID가 필요하지 않으며 해당 동작은 표준에 명시적으로 정의되어 있습니다.

추가 고려 사항

  • CWG 문제 #232는 처리 간의 불일치를 강조합니다. C 표준에서 널 포인터를 통한 간접 참조는 본질적으로 정의되지 않은 동작으로 이어지지 않을 수 있음을 시사합니다.
  • CWG 문제 #315는 특히 널 포인터를 통해 멤버 함수를 호출하는 시나리오를 다루며 간접 참조 자체가 개체 ID에 의존하는 추가 작업이 포함되지 않는 한 오류가 아닙니다.
  • 식의 결과(삭제된 값 식)를 삭제하는 것은 값에 액세스하는 것과 다르게 처리되며, 이는 컨텍스트에 따라 오류를 유발할 수 있습니다.

결론

정적 멤버 액세스 컨텍스트에서 *d 평가가 허용되므로 해당 프로그램은 아무런 해를 끼치지 않습니다. 널 포인터를 통한 간접 참조가 반드시 정의되지 않은 동작을 발생시키는 것은 아니지만 객체 ID가 필요한 추가 작업과 관련된 잠재적인 위험을 인식하는 것이 중요합니다.

위 내용은 C에서 널 포인터를 사용하여 정적 멤버에 액세스하는 것이 허용되는 이유는 무엇입니까?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.