2011-12-18 6 views
5

: 상이한 유형의 객체에* CHAR 변환 규칙 앨리어싱

char*
struct B { virtual ~B() {} }; 
struct D : public B { }; 

D d; 
char *c = reinterpret_cast<char*>(&d); 

유효하다. 하지만 이제 질문은 & d의 동일한 주소를 가리 킵니까? 동일한 주소를 반환한다는 C++ 표준의 보장은 무엇입니까?

+9

당신의 소멸자가 잘못 명명 된 것 같습니다. –

+4

나는 답을 모른다. 그러나 언제이 지식이 언제 실제로 유용할까요? –

+0

좋은 질문입니다. 일부 캐스트는 실제로 주소를 변경할 수 있습니다 (예 : 다중 상속이 관련된 경우).나는 그것이 사실인지 궁금해. – Kos

답변

6

c&d 실제로 같은 값을 가지고 있고, 당신이 경우에 당신은 당신이 역 참조 할 수있다 유효한 포인터를 얻을 다시 D*-c을 재 해석 캐스트 않습니다. 또한 c을 불투명 한 배열 char[sizeof(D)]의 첫 번째 요소로 처리 할 수 ​​있습니다. 이것은 참으로 char 포인터에 대한 포인터를 형 변환하는 주된 목적입니다. 직렬화를 허용하려면 (예 : ofile.write(c, sizeof(D));) 일반적으로 복합 형의 바이너리 레이아웃이 일반적으로 이동식으로 지정되지 않기 때문에 원시 형 (및 배열)에 대해이 작업을 수행하십시오.

@Oli가 올바르게 지적하고 강조하기를 바라지 만 전체적으로 복합 유형을 직렬화해서는 안됩니다. 데이터 필드 사이의 다형 클래스 및 패딩 구현이 지정되지 않았고 사용자가 액세스 할 수 없으므로 결과는 거의 직렬화 할 수 없습니다.

유사한 이유에 의해 reinterpret_cast<char*>(static_cast<B*>(&d))은 불투명 한 배열 char[sizeof(B)]으로 처리 될 수 있습니다.

+0

아마도 이처럼 비 POD 클래스 (즉, vptrs가있는 클래스)를 직렬화/비 직렬화하는 것은 매우 나쁜 생각이라는 점을 분명히해야한다고 생각합니다. –

+0

@OliCharlesworth : 흠, * objects *에는 숨겨진 "vptrs"가 없습니다. 클래스 구현에만 있습니다. 가상 상속에 들어갈 때까지 객체는 여전히 "보통"레이아웃을 유지해야합니다. 일반적인 패딩 문제는 "순진한"방식으로 클래스 유형을 직렬화하지 않는 훨씬 더 직접적인 이유입니다. 상황이 괜찮은 경우 (예 : 메모리 매핑 네트워크 I/O를 사용하는 동일한 시스템의 HPC 클러스터 ...). 구매자 조심 :-) –

+0

무엇? 가상 함수의 존재는 클래스 인스턴스가 vptr을 가져야 함을 의미합니다 (모든 일반적인 구현에서). –

2

제 5.2.10, 2003 년 C++ 표준의 점 (7)는 말한다 : 객체에

포인터가 명시 적으로 다른 유형의 객체에 대한 포인터로 변환 할 수 있습니다."T2 포인터"유형 (T1 및 T2는 오브젝트 유형이고 T2의 정렬 요구 사항은 T1보다 엄격한 이 아니며 유형은 ) 유형의 유형으로 "T1에 대한 포인터"유형을 변환하는 것을 제외하고는 원래 유형은 원래 포인터 값을 산출하고, 그러한 포인터 변환의 결과는 지정되지 않은 입니다.

"동일한 주소"로 "원래 포인터 값"을 의미하는 경우이 항목에 "예"가 표시됩니다. 대상 유형은 작은 정수 형과 같이 (모든 주소 값을 나타내지 않는 한

reinterpret_cast는, 주소의 값을 변경하지 :

0

의도는 분명 (토론해야하지 뭔가)입니다 f.ex. 짝수 주소 만 나타낼 수있는 포인터 또는 함수에 대한 객체 및 포인터에 대한 포인터를 혼합 할 수없는 ...).

표준의 표현은이를 포착하지 못했지만 실제로는 실제적인 문제가 있음을 의미하지는 않습니다.

char *c = reinterpret_cast<char*>(&d); 

c 항상 d의 첫 번째 바이트를 가리 킵니다.