C에서 0에 대한 포인터 역 참조
때때로 메모리 주소 0x0의 데이터는 매우 가치가 있습니다. x86 리얼 모드 IVT를 더 잘 알려진 예로 생각해보십시오 : 0x0에서 시작하고 인터럽트 핸들러에 대한 포인터를 포함합니다. 0x00에있는 dword는 0으로 나누는 오류 핸들러에 대한 포인터입니다.
그러나 C11 언어 표준 은 0으로 초기화 된 포인터 또는 널 포인터로 초기화 된 포인터 [WG14 N1570 6.3.2.3] 로 정의 된 널 포인터 [WG14 N1570 6.5.3.2]의 역 참조를 금지하여 첫 번째 바이트를 효과적으로 금지합니다.
사람들은 필요할 때 실제로 0x0을 어떻게 사용합니까?
C는 널 포인터의 역 참조를 금지 하지 않고 정의되지 않은 동작을 만듭니다.
주소를 포함하는 포인터를 역 참조 할 수있는 환경이라면 0x0
그렇게 할 수 있어야합니다. C 언어 표준은 그렇게 할 때 일어날 일에 대해 아무것도 말하지 않습니다. (대부분의 환경에서 결과는 프로그램 충돌입니다.)
구체적인 예 (정확히 기억하고 있다면) : 68k 기반 Sun 3 컴퓨터에서 널 포인터를 역 참조해도 트랩이 발생하지 않았습니다. 대신 OS는 메모리 주소 0에 0 값을 저장했고, null 포인터 (주소 0을 가리킴)를 역 참조하면 해당 0 값이 생성됩니다. 예를 들어, C 프로그램은 널 포인터를 마치 빈 문자열에 대한 유효한 포인터처럼 취급 할 수 있습니다. 일부 소프트웨어는 의도적이든 아니든이 동작에 의존했습니다. 이를 위해서는 널 포인터 역 참조에 갇힌 SPARC 기반 Sun 4로 소프트웨어를 포팅 할 때 많은 정리가 필요했습니다. (나는 이것에 대해 읽은 것을 분명히 기억하지만 참조를 찾을 수 없었습니다. 찾을 수 있으면 업데이트하겠습니다.)
널 포인터가 주소가 0 일 필요 는 없습니다 . 보다 정확하게는 null의 표현이 모두 0 비트 일 수도 있고 아닐 수도 있습니다. 매우 일반적이지만 보장되지는 않습니다. (그렇지 않은 경우 정수에서 포인터로의 변환은 (void*)0
중요하지 않습니다.)
comp.lang.c FAQ 의 섹션 5 에서는 널 포인터에 대해 설명합니다.
사람들은 필요할 때 실제로 0x0을 어떻게 사용합니까?
중 하나에 의해:
- 어셈블리 언어로 필요한 코드 작성 또는
- C로 코드를 작성하고 컴파일러가 원하는 작업에 대해 올바른 어셈블리 언어를 생성하는지 확인
진술 :
char * x = 0;
반드시 0x0을 x에 넣지는 않습니다. 현재 아키텍처 및 컴파일러에 대해 정의 된 널 포인터 값을 x에 넣습니다.
이제 실질적인 측면에서 일반적으로 사용되는 모든 컴파일러 / 프로세서는 해당 명령문에 대한 응답으로 레지스터 또는 저장 위치의 행에 32 (또는 64) 0 비트를 넣습니다. 따라서 메모리 주소 0이 유용하다면, 그런 다음 다른 사람들이 지적했듯이 공식적으로 정의되지 않은 동작을 사용하고 있습니다. 그러나 옛날 옛적에 '널 포인터'가 모두 0 이 아닌 비트 패턴 인 하드웨어가 있었고 , 누가 알겠는가?
Annex J 다음과 같은 경우 정의되지 않은 동작입니다.
단항 * 연산자의 피연산자에 유효하지 않은 값 (6.5.3.2)이 있습니다.
언급 한 동일한 각주에서 널 포인터는 유효하지 않은 값이라고 말합니다. 따라서 금지 된 것이 아니라 정의되지 않은 동작입니다. 주소 0x0
와 널 포인터 의 구별 에 대해서는 메모리 주소 0x0을 사용할 수 있습니까?를 참조하십시오 . .
널 포인터가 반드시 주소 0x0 일 필요는 없으므로 아키텍처는 잠재적으로 다른 주소를 선택하여 널 포인터를 나타낼 수 있으며 new에서 유효한 주소로 0x0을 얻을 수 있습니다.
null 포인터가 Operative System에 의해 예약되었는지 또는 C ++ 구현에 의해 예약되었는지 여부는 지정되지 않았지만, plain new는 주소가 무엇이든간에 null 포인터를 반환하지 않습니다 (new new는 다른 짐승이 아닙니다). 따라서 귀하의 질문에 답하려면 :
메모리 주소 0x0을 사용할 수 있습니까?
아마도 특정 구현 / 아키텍처에 따라 다릅니다.
즉, 0x0
시스템에서 충돌을 일으키지 않는다고 확신한다면 자유롭게 사용 하십시오.
운영 체제는 포인터 테이블을 사용하여 루틴을 인터럽트하여 적절한 인터럽트를 호출합니다. 일반적으로 (대부분의 운영 체제에서) 포인터 테이블은 낮은 메모리 ( 처음 수백 개 정도의 위치)에 저장됩니다. 이러한 위치는 다양한 장치에 대한 인터럽트 서비스 루틴의 주소를 보유합니다.
그래서 당신이 할 때
char *ptr = 0x0;
그런 다음 인터럽트 서비스 루틴의 주소로 포인터를 초기화 할 가능성이 높습니다. 운영 체제에 속한 메모리 위치를 역 참조 (또는 수정)하면 프로그램이 충돌 할 가능성이 높습니다.
따라서 0x0
OS에 속하지 않는다는 확인을받을 때까지 포인터를 초기화 하고 역 참조하지 않는 것이 좋습니다.
참조 URL : https://stackoverflow.com/questions/21104702/dereferencing-a-pointer-to-0-in-c
'program tip' 카테고리의 다른 글
멱등 함수는 순수 함수와 동일합니까? (0) | 2021.01.08 |
---|---|
양식에 동적으로 필드 추가 (0) | 2021.01.08 |
프로세스 ID로 프로세스 이름 찾기 (0) | 2021.01.08 |
IOHIDFamily의 미스터리 콘솔 오류 (0) | 2021.01.08 |
sourcetree를 사용하여 git rebase (0) | 2021.01.08 |