2014-08-27 5 views
7

char을 가리키는 데 필요한 정보가 int (주소 지정이 불가능한 바이트를 가진 플랫폼이므로 char에 대한 포인터는 단어에 대한 포인터를 저장할 필요가있는 것보다 더 많은 정보가 필요하다는 것을 알고 있습니다. 단어의 바이트 인덱스). 따라서 해당 플랫폼에서는 sizeof(int*) < sizeof(char*) 일 수 있습니다.비 유니온 클래스에 대한 포인터의 크기가 다를 수 있습니까?

non-union 클래스에 대한 포인터와 비슷한 것이 발생할 수 있습니까? C++은 가상 함수에서 공변 리턴 유형을 허용합니다. 이제 우리는이 같은 수업을 가정 해 봅시다 :

struct Gadget 
{ 
    // some content 
}; 


struct Widget 
{ 
    virtual Gadget* getGadget(); 
}; 
getGadget()Gadget*를받을 때 작동하는 전화 코드,하지만 같은 코드 (실제로 같은 이진 코드를 컴파일이)가 포인터를받을 때 일해야

Gadget (아마도 완전히 다른 라이브러리에 정의 된 라이브러리)에서 파생 된 유형으로 변환 할 수 있습니다. 합법적으로 볼 수있는 유일한 방법은 모든 비 유니언 클래스 유형 및 U에 대해 sizeof(T*) == sizeof(U*)입니다.

내 질문에 하나의 특정 플랫폼에서 특정 컴파일러 (가상의 Hell ++ 제외)가 주어진 경우 비공개 클래스 유형에 대한 모든 포인터가 동일한 크기가 될 것으로 예상하는 것이 합리적입니까? 아니면 컴파일러가 공변 반환 유형을 준수하면서 다른 크기를 사용하려는 이유가 있습니까? 포인터의 다른 "수준"(예 : __near__far으로) 존재 플랫폼

은, 모두에 적용되는 같은 속성을 가정합니다.

+0

사이드 노트 : 데이터 포인터와 코드 포인터의 크기가 다른 임베디드 분야에는 많은 예제가 있습니다. – Lindydancer

+0

@Lindydancer 물론. 하지만 나는 데이터 포인터에 대해서만 명시 적으로 요구하고 있으며, 그 부분 집합에 대해서만 요구하고있다. – Angew

+0

@Casey'language-lawyer'가 이미 추가되고 한 번 제거되었습니다. 해당 사항이 확실합니까? 결국, 실용적인 바보 같은 일을하면서 표준의 서신을 따르는 가설적인 것이 아니라 실제 구현에 대해 묻고 있습니다. – Angew

답변

4

C는 모든 구조 유형에 대한 모든 포인터가 동일한 표현과 정렬을 갖도록 요구합니다. 유형을 구조화

6.2.5 유형

27 [...] 모든 포인터들은 서로 같은 표현 및 정렬 요건을 가진다. [...]

C 효과적으로 때문에 extern "C"에 대한 표준의 요구 사항으로는 C 구현 바이너리 호환성을 필요 ++, 그래서 간접적으로이 꽤 많이, (C에서 POD 유형 유효한 유형을 구성하는 모든 포인터를 필요로) C++에서도 동일한 표현과 정렬을가집니다.

이러한 요구 사항은 비 POD 유형에 대해서는 작성되지 않았으므로, 구현시 다른 포인터 크기를 사용할 수 있습니다.당신은

struct G { }; 
struct H : G { }; 

struct W 
{ 
    virtual G* f() { ... } 
}; 
struct X : W 
{ 
    virtual H* f() { ... } 
}; 

여전히 언어의 요구 사항과 일치합니다 (의사 코드)

struct W 
{ 
    virtual G* f() { ... } 
}; 
struct X : W 
{ 
    override G* f() { ... } 
    inline H* __X_f() { return static_cast<H *>(f()); } 
}; 

로 번역 될 수있는, 즉 작동하지 않을 수 있지만 예를 따르도록하는 것이 좋습니다.

구조 유형에 대한 두 포인터가 동일하지 않은 유효한 이유는 C++ 컴파일러가 잘못 설계된 ABI가있는 기존 C 컴파일러가있는 플랫폼으로 이식 될 때입니다. G은 POD 유형이므로 G *은 정확히 C에 있어야합니다. H은 POD 유형이 아니므로 H *은 C 유형과 일치 할 필요가 없습니다.

정렬을 위해 실제로 일어날 수있는 일이 있습니다. 일반적인 GNU/Linux 시스템의 x86-32 ABI는 프로세서의 기본 정렬이 64 비트 정수 유형이 32 비트 정렬이어야합니다. 실제로는 64 비트입니다. 이제 또 다른 구현자가 나오고 64 비트 정렬을 원한다고 결정하지만 기존 구현과 호환되도록 유지하려는 경우 혼란 스럽습니다.

크기의 경우 합리적인 시나리오를 생각할 수는 없지만 그 부분이 상상력이 부족한 것인지 확실하지 않습니다.

+0

'G'가 'H'의 비 다형성 가상 기본 클래스이고 [static_cast (또는 다른 캐스트)가 가능하지 않더라도] 그러한 트릭의 구현이 가능할 것이라고 생각하십니까? (http : //stackoverflow.com/a/24920749/1782465)? – Angew

+1

@Angew 좋은 질문입니다. 그렇습니다. 그런 트릭은 여전히 ​​가능합니다. 다른 방법으로 처리하면됩니다. 의사 코드는 override G * f() final {return __X_f(); } virtual H * __X_f() {...}'컴파일러는'f'의 오버라이드가 실제로'__X_f'의 오버라이드를 끝내도록 보장해야합니다. – hvd

+1

@Angew 사실, 생각해 보면, 컴파일러는 이미'derived * '가 단순히'기본 *'으로 재 해석 될 수 없을 때 (이미 그 예를 포함해서) 실제로 그렇게 할 필요가 있습니다. – hvd

0

지금까지 C와 C++에서 메모리는 선형으로 주소 지정이 가능하다고 가정합니다. 그러나 특정 플랫폼 (초기 ARM)은 단어 정렬로드 및 저장을 요구합니다. 이런 경우 컴파일러는 포인터를 단어 경계로 반올림 한 다음 문자를 가져올 때 필요한 비트 시프트 연산을 수행해야합니다.

하지만이 작업은 모두로드 및 저장에서만 수행되므로 모든 포인터는 여전히 동일하게 보입니다.