간략한 요약
(또한 맨 위에 두겠습니다) :
(0) 포인터를 주소로 생각하는 것은 종종 좋은 학습 도구이며 종종 일반 데이터 유형에 대한 포인터의 실제 구현입니다.
(1) 그러나 대부분의 경우 함수에 대한 컴파일러 포인터는 주소가 아니지만 주소보다 크거나 (일반적으로 2 배 이상, 때로는 더 많음) 실제로 함수의 주소와 내용을 포함하는 것보다 메모리의 구조체에 대한 포인터입니다 일정한 수영장.
(2) 데이터 멤버에 대한 포인터와 메서드에 대한 포인터는 종종 낯선 것입니다.
FAR 및 NEAR 포인터 문제가있는 레거시 x86 코드
(4) 안전한 "뚱뚱한 포인터"를 가진 몇 가지 예, 특히 IBM AS / 400.
더 많이 찾을 수있을 것입니다.
세부 묘사:
UMMPPHHH !!!!! 지금까지 많은 답변이 상당히 일반적인 "프로그래머 weenie"답변이지만 컴파일러 weenie 또는 하드웨어 weenie는 아닙니다. 나는 하드웨어 weenie 인 척하고 종종 컴파일러 weenies와 함께 일하기 때문에 2 센트를 던져 보자.
아마도 대부분의 C 컴파일러에서 유형의 데이터에 대한 포인터 T
는 실제로 주소입니다 T
.
좋아.
그러나 이러한 많은 컴파일러에서도 특정 포인터는 주소가 아닙니다. 를 보면 알 수 있습니다 sizeof(ThePointer)
.
예를 들어, 함수에 대한 포인터는 때때로 일반 주소보다 훨씬 더 큽니다. 또는 간접적 인 수준이 관련 될 수 있습니다. 이 기사Intel Itanium 프로세서와 관련된 하나의 설명을 제공하지만 다른 것을 보았습니다. 일반적으로 함수를 호출하려면 함수 코드의 주소뿐만 아니라 함수의 상수 풀 주소도 알아야합니다. 즉, 컴파일러가 생성하지 않고 상수가 단일로드 명령으로로드되는 메모리 영역입니다. 여러 Load Immediate 및 Shift 및 OR 명령어 중 64 비트 상수 따라서 단일 64 비트 주소가 아니라 2 개의 64 비트 주소가 필요합니다. 일부 ABI (Application Binary Interfaces)는이 비트를 128 비트로 이동하는 반면, 다른 ABI (기능 이진 인터페이스)는 간접적 인 수준을 사용하며 함수 포인터는 실제로 2 개의 실제 주소를 포함하는 함수 설명 자의 주소입니다. 어떤게 더 좋아? 관점, 성능, 코드 크기, 그리고 일부 호환성 문제-종종 코드는 포인터가 길거나 길다고 캐스팅 될 수 있다고 가정하지만, long long이 정확히 64 비트라고 가정 할 수도 있습니다. 이러한 코드는 표준을 준수하지 않을 수 있지만 고객이 작동하기를 원할 수 있습니다.
우리 중 다수는 NEAR POINTER 및 FAR POINTERS와 함께 이전 Intel x86 세그먼트 아키텍처에 대한 고통스러운 기억을 가지고 있습니다. 고맙게도 이것들은 지금까지 거의 멸종되었으므로 간단히 요약하면됩니다. 16 비트 실제 모드에서 실제 선형 주소는
LinearAddress = SegmentRegister[SegNum].base << 4 + Offset
보호 모드 인 경우에는
LinearAddress = SegmentRegister[SegNum].base + offset
결과 주소가 세그먼트에 설정된 한계에 대해 검사됩니다. 일부 프로그램은 실제로 표준 C / C ++ FAR 및 NEAR 포인터 선언을 사용하지 않았지만 대부분은 *T
--- 라고 말 했지만 컴파일러와 링커 스위치가 있으므로 코드 포인터가 포인터 근처에있을 수 있습니다. CS (코드 세그먼트) 레지스터, 데이터 포인터는 FAR 포인터 일 수 있으며 48 비트 값에 대해 16 비트 세그먼트 번호와 32 비트 오프셋을 모두 지정합니다. 이제이 두 가지 수량은 모두 주소와 관련이 있지만 같은 크기가 아니기 때문에 어떤 주소입니까? 또한 세그먼트에는 실제 주소와 관련된 항목 외에도 권한 (읽기 전용, 읽기-쓰기, 실행 가능)이 포함되었습니다.
보다 흥미로운 예인 IMHO는 IBM AS / 400 제품군입니다. 이 컴퓨터는 C ++로 OS를 구현 한 최초의 컴퓨터 중 하나였습니다. 이 machime에 대한 포인터는 일반적으로 실제 주소 크기 2X했다 -로 예 프리젠 테이션128 비트 포인터이지만 실제 주소는 48-64 비트였으며 다시 한 번 기능이라고 불리는 추가 정보는 읽기, 쓰기 및 버퍼 오버플로를 방지하기위한 제한과 같은 권한을 제공했습니다. 예 : C / C ++를 사용하여이 작업을 수행 할 수 있으며, 이것이 보편적 인 경우 중국 PLA와 슬라브 마피아는 많은 서양 컴퓨터 시스템을 해킹하지 않을 것입니다. 그러나 역사적으로 대부분의 C / C ++ 프로그래밍은 성능에 대한 보안을 무시했습니다. 가장 흥미롭게도, AS400 제품군은 운영 체제가 권한없는 코드에 제공 될 수 있지만 권한이없는 코드는 위조하거나 조작 할 수없는 보안 포인터를 작성할 수 있도록 허용했습니다. 다시 말하지만 보안은 표준을 준수하지만, 비 규격 비 규격 호환 C / C ++ 코드는 보안 시스템에서 작동하지 않습니다. 다시 한 번 공식 표준이 있습니다.
이제 보안 비누 상자에서 벗어나 다양한 유형의 포인터가 실제로 주소가 아닌 다른 방법을 언급합니다. 데이터 멤버에 대한 포인터, 멤버 함수 메소드에 대한 포인터 및 정적 버전이 보통 주소. 마찬가지로 이 게시물은 말합니다 :
이를 해결하는 방법에는 여러 가지가 있습니다 [단일 대 다중 상속 및 가상 상속과 관련된 문제]. Visual Studio 컴파일러가이를 처리하기로 결정한 방법은 다음과 같습니다. 다중 상속 클래스의 멤버 함수에 대한 포인터는 실제로 구조입니다. "그리고"함수 포인터를 캐스팅하면 크기를 변경할 수 있습니다! "라고 말합니다.
보안에 대한 가능성을 짐작할 수 있듯이 포인터가 원시 주소보다 기능처럼 취급되는 C / C ++ 하드웨어 / 소프트웨어 프로젝트에 참여했습니다.
계속할 수는 있지만 아이디어를 얻길 바랍니다.
간략한 요약
(또한 맨 위에 두겠습니다) :
(0) 포인터를 주소로 생각하는 것은 종종 좋은 학습 도구이며 종종 일반 데이터 유형에 대한 포인터의 실제 구현입니다.
(1) 그러나 대부분의 경우 함수에 대한 컴파일러 포인터는 주소가 아니지만 주소보다 크거나 (일반적으로 2X 이상) 실제로 함수의 주소와 내용을 포함하는 것보다 메모리의 구조체에 대한 포인터입니다 일정한 수영장.
(2) 데이터 멤버에 대한 포인터와 메서드에 대한 포인터는 종종 낯선 것입니다.
FAR 및 NEAR 포인터 문제가있는 레거시 x86 코드
(4) 안전한 "뚱뚱한 포인터"를 가진 몇 가지 예, 특히 IBM AS / 400.
더 많이 찾을 수있을 것입니다.