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.