0x0 위치를 가리키는 포인터와 NULL로 설정된 포인터의 차이점은 무엇입니까?


12

0x0000을 가리키는 포인터가 NULL로 설정된 포인터와 동일합니까? C 언어로 NULL 값을 정의하면 물리적으로 어떤 위치로 변환됩니까? 0x0000과 동일합니까? 이러한 개념에 대한 자세한 내용은 어디서 찾을 수 있습니까?


1
이것은 이미 스택 오버플로에 요구하고있다 - stackoverflow.com/questions/1296843/...을 . 나는 그것이 우리의 경계라고 생각하지만, 나는 그것이 의심의 이익을 기꺼이 줄 것입니다.
ChrisF

답변:


12

여기서 명시 적으로 언급하지 않은 대부분의 대답은 null 포인터 는 실행 중에 존재하는 값이고 null 포인터 상수 는 C 소스 코드에 존재하는 구문 구조입니다.

NULL 포인터 상수 Karlson의 답변이 제대로 상태로, 하나의 값 0 (a 간단한와 정수 상수 표현이다 0가장 흔한 예이다), 또는 그러한 발현 캐스트 void*(예 (void*)0).

NULL매크로 <stddef.h>는 구현 표준 널 포인터 상수로 확장 되는 매크로 및 기타 여러 표준 헤더로 정의 됩니다 . 확장은 일반적으로 0또는 ((void*)0)다른 언어 규칙을 충족시키기 위해 외부 괄호가 필요합니다.

따라서 리터럴 0은 포인터 유형의 표현식이 필요한 컨텍스트에서 사용될 때 항상null pointer 객체를 가리 키지 않는 고유 포인터 값으로 평가됩니다 . 그것은 널 포인터 의 표현에 대해 아무 것도 암시 하지 않습니다 . 널 포인터는 일반적으로 모두 0으로 표시되지만 아무 것도 표시 할 수 있습니다. 그러나 널 포인터로 표현 된 경우에도 , 또는 아직도이다 널 포인터 상수 .0xDEADBEEF0(void*)0

stackoverflow관한 질문에 대한 대답 은 이것을 잘 다루고 있습니다.

이것은 다른 것들 사이에, 의미 memset()또는 calloc()모든 비트 제로에 메모리의 영역을 설정할 수 있습니다, 반드시 널 포인터에 그 지역에있는 포인터를 설정하지 않습니다. 대부분의 구현에서 그렇게 할 가능성이 있지만 언어가 보장하지는 않습니다.

이 질문의 중복으로 간주되지 않는 이유를 모르겠어요 이 하나 , 또는 여기 화제의 방법에 대해 설명합니다.


1
C의 디자인과 진화에 대한 나의 견해 중 하나는 숫자 0이 계속 사용되지 않는 null 포인터 표현으로 계속 사용되었다는 것입니다. 언어의 초기 (예 : 함수 프로토 타입과 같은 것들이 출현하기 전)로 돌아가서, 포인터와 정수는 널 포인터에 "0"을 사용하는 것이 간단하고 "그냥 작동"할 정도로 충분히 상호 교환이 가능했습니다. 그러나 정수 수량 0과 널 포인터를 구별해야하는 경우 키워드 또는 연산자 순서를 위해 "0"표시가 사용되지 않아야합니다.
supercat

이것은 플랫폼에 따라 NULL 포인터가 NULL로 할당 될 때 NULL 포인터가 실제로 어떤 위치를 가리킬 수 있음을 의미합니까? 널 포인터 상수는 구문 구조 일 수 있지만 코드가 실행될 때 정확히 어떻게됩니까? 이 구문 구조가 GNU / Linux 플랫폼에서 컴파일되었다고 가정 해 봅시다. NULL을 할당 할 때 포인터 값은 무엇입니까? 이 주소는 다른 주소와 어떻게 다릅니 까?
Arpith

1
@Arpith : 포인터 객체에 NULL, 또는 null 포인터 상수를 할당하면 해당 객체의 값이 null 포인터로 설정 됩니다. 머신 레벨에서 유효한 메모리 덩어리를 가리킬 수 있습니다. 널 포인터를 역 참조하면 동작이 정의되지 않습니다. 주소에서 메모리 청크에 액세스하는 0x0000000것은 문자 그대로 다른 것과 마찬가지로 유효한 동작입니다. 이 주소는 NULL(a)와 같음 비교 및 (b) C 객체에 대한 포인터와 같지 않은 비교를 통해 다른 주소와 다릅니다 . 널 포인터는 아무 것도 가리 키지 않음을 나타내는 데 사용되는 임의의 포인터 값입니다.
Keith Thompson

1
머신 레벨 에서는 유효한 메모리 덩어리를 가리킬 있지만 대부분의 C 환경에서는 유효하지 않은 메모리를 가리 키므로 포인터를 사용하면 하드웨어 트랩 / 결함 / 예외가 발생합니다. 일반적으로 메모리 관리를 지원하지 않는 가장 간단한 하드웨어 플랫폼에만 있습니다. 여기서 NULL 포인터는 유효한 메모리 위치를 가리 킵니다.
Solomon Slow

7

모든 플랫폼은 원하는대로 NULL을 자유롭게 정의 할 수 있습니다.

C 표준에 따르면 포인터에 0을 할당하면 해당 플랫폼의 경우 NULL 값으로 변환됩니다. 그러나 NULL 포인터를 가져 와서 int로 캐스팅하면 0을 얻을 것이라는 보장이 없습니다. 모든 플랫폼에서 그러나 사실 대부분의 플랫폼에서는 0이 될 것입니다.

해당 언어 에 대한 정보는 C 언어 사양 에서 찾을 수 있습니다 . 보증 할 수없는 한 가지 출처는 다음과 같습니다. http://www.winapi.co.kr/pds/doc/ISO-C-FDIS.1999-04.pdf


2
그들이 표준에서 벗어나기로 선택하면 자유롭게 재정의 할 수 NULL pointer constant있습니다. 내가 아는 한, 거기에는 컴파일러가 없습니다.
Karlson

NULL을 0으로 구현하지 않는 컴파일러가 있습니까? 그리고 NULL이 거짓으로 평가되도록 보장됩니까?
ugoren

NULL은 표준에 의해 false로 평가됩니다. NULL을 0으로 구현하지 않는 컴파일러 (실제로 플랫폼)가 있는지는 모르겠지만 심각하게 의심하지만 표준은 그것을 금지하지 않으므로 누가 압니다.
Mike Nakis

플랫폼 제조업체가 좋아할 수있는 메모리의 추상 "널 포인터 상수"(사양에 언급 된 바와 같이) 표현과 C ++ 및 C 또는 C에서 NULL확장 해야하는 매크로 의 정의간에 혼동이 있습니다 . 왜냐하면 이것이 "널 포인터 상수"이기 때문입니다. 00(void *)0
Jan Hudec

이론적으로 NULL은 무엇이든 정의 할 수 있지만 표준에 의해 포인터에 0으로 형변환 된 int 상수는 널 포인터 (ISO 9899 : 1999 6.3.2.3/3)가된다는 보장이 있습니다. stddef.h의 NULL 매크로는 널 포인터 (7.17 / 3) 여야하므로 컴파일러에서 NULL을 0 또는 (void *) 0으로 구현하지 않는 것은 매우 부담이됩니다.

1

동일하지 않은 머신 주소가 없기 때문에 C 언어로 정의 됩니다. 그렇다면 추상화가 필요하지 않습니다! 대부분의 플랫폼에서 NULL은 결국 어떤 유형의 0 또는 다른 유형으로 구현 될 수 있지만 이식성에 관심이 있다면 이것이 보편적이라고 가정하는 것은 잘못입니다.



0

C 표준 문서 섹션 에 따르면 6.3.2.3:

값이 0 인 정수 상수 표현식 또는 void * 유형으로 캐스트되는 표현식을 널 포인터 상수라고합니다 .55) 널 포인터 상수가 포인터 유형으로 변환되면 결과 포인터 (널 포인터)는 다음과 같습니다. 객체 또는 함수에 대한 포인터와 같지 않은 비교를 보장합니다.

지금까지 나는 이것에서 벗어난 컴파일러를 보지 못했습니다.


@ PéterTörök 당신은 맞습니다. :)
Karlson

1
예, 그러나 실제로 숫자 값이 0 인 포인터에 대해서는 아무 것도 말하지 않습니다. 대부분의 플랫폼에서는 그렇지 않습니다.
Jan Hudec
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.