2010-07-21 5 views
10

C++ 표준에 따르면, 구현에 따라 Q*can change or not change the pointer value 포인터에 T* 다른 종류의 포인터 reinterpret_cast이 있습니다.포인터 값을 변경하는 reinterpret_cast의 실제 예는 무엇입니까?

저는 매우 흥미 롭습니다. reinterpret_cast을 사용하여 다른 포인터 유형에 대한 포인터를 캐스팅 한 포인터가 포인터를 변경하는 C++ 구현의 실제 예가 있습니까? 왜 그리고 왜 변경 되었습니까?

+0

포인터가 가리키는 "값을 변경"한다는 의미입니까? – akira

+0

@akira : 아니요, 포인터 자체의 값을 변경합니다 – sharptooth

+0

다음과 같은 의미입니다 :'T * t = 0x13; Q * q = 0x42; t = reintrepret_cast (q);''t! = 0x42'? – akira

답변

6

표준에 무엇인가를 할 수 있거나 할 수 없다는 것이 명시되어 있다면 그것이 현재 가능한 모든 동작이 있다는 것을 의미하지는 않습니다.

내가 생각할 수있는 가장 가까운 것은 하드웨어에서 유형 정렬이 필요한 아키텍처와 필요한 경우 정렬을 수정하기로 결정한 구현입니다. 같은 뭔가 : 낮은 정렬 요구 사항에 인수 q 어떤 메모리 주소를 가리 수 있지만

aligned8 var; 
aligned1 *p = reinterpret_cast<aligned1*>(&var); 
aligned1 *q = p + 1; // assuming aligned 1 size is not multiple of 8 
aligned8 *a = reinterpret_cast<aligned8*>(q); // [1] 

a 것이 8의 메모리 위치의 복수를 해결하는 유효한 포인터가 될 수있는 요구 사항이있을 수 있습니다.

2
class A1 { int a1; }; 
class A2 { int a2; }; 

class B: public A1, public A2 { }; 

#define DBG(val) cout << #val << ": " << val << endl 

// test code 
B b; 
DBG(&b);           // prints 0x42 

void *p_blank = &b; 
DBG(p_blank);          // prints 0x42 
A2 *p_a2 = &b; 
DBG(p_a2);           // prints 0x46 
void *p_reinterpreted = reinterpret_cast<A2*>(&b); 
DBG(p_reinterpreted);        // prints 0x42 
A2 *p_reinterpreted2 = reinterpret_cast<A2*>(&b); 
DBG(p_reinterpreted2);        // prints 0x42 

A2 *p_a2 = &b 수단 ㄴ 객체 A2 내의 객체 내게 포인터를 제공한다. reinterpret_cast<A2*>(&b) 의미는 입니다. b에 대한 포인터를 제공하고 A2 포인터로 처리합니다.. 이 reinterpret_cast의 결과는 'A2에 대한 포인터'유형을 가지므로 void * 변수 (또는 A2 * 변수)에 할당 될 때 경고를 생성하지 않습니다.

+0

'A2 * p_a2 = & b;'놀라워요 ... – akira

+5

예에서'reinterpret_cast'는 값을 전혀 바꾸지 않습니다 ... 당신은 꺼려합니다. –

+0

'A2 * p_a2 = & b;'에서'reinterpret_cast'가 아닌'static_cast'와 동일한 암시 적 변환을 사용합니다. – sharptooth

0

Reinterpret_cast는 다른 주소를 반환하지 않습니다. 정확한 주소를 복사해야합니다.

데이비드로드 리 게스 (David Rodriguez)와 같이 다중 상속의 경우베이스 중 하나의 주소를 가져 가면 첫 번째 기준의 주소에 오프셋이있는 주소가 반환 될 수 있습니다. Reinterpret_cast는 오프셋 주소를 반환하지만 업 캐스트 주소로 처리하면 지옥이 계속됩니다.

업 캐스팅의 경우 static_cast는 주어진 주소와 다른 주소를 반환 할 수 있습니다. 갖고있는 주소가 기지 중 하나이고 해당 주소가 첫 번째 기본 주소의 오프셋에있는 경우 static_cast는 첫 번째 기본 주소와 같으므로 업 캐스팅 된 객체에 유효한 주소를 반환합니다 전달 된 포인터에.

짧게하려면 : reinterpret_cast는 항상 동일한 주소를 제공합니다. Static_cast 및 dynamic_cast는 다른 주소를 반환 할 수 있습니다 (예 : 어떤 경우에는 다중 상속이 필요합니다.

static_cast와 dynamic_cast의 차이점은 static_cast가 지정한 포인터가 캐스트에 적합한 개체인지 여부를 확인하지 않기 때문에 호출하기 전에 static_cast에서 해당 개체를 확인해야한다는 것입니다.

+1

"필수"와 관련된 문구는 원본으로 백업해야합니다. 내가 본 모든 것은 당신이 덜 엄격하게 정렬 된 타입 *의 포인터로 변환 할 수 있다는 것입니다. 그리고 "* 다른 포인터 변환의 결과는 지정되지 않았습니다." (5.2.10/7) – Potatoswatter

+1

음, 정렬 문제를 완전히 놓쳤습니다. 주소가 어떻게 바뀌는 지 알 수 있습니다. 수정 해줘서 고마워. – Alex

1

가장 큰 문제의 근원은 스칼라 연산이 벡터의 관점에서 정의되는 벡터 시스템에 있으며 스칼라 포인터는 벡터에 대한 인덱스가있는 벡터에 대한 포인터로 구성됩니다. 역사적으로 원래의 Cray 아키텍처는 이와 같았고 두통을 불러 일으켰습니다. 요즘에는 GPU에서 이와 비슷한 것을 볼 수 있지만, 머리 꼭대기에서 뭔가 구체적인 것을 지적 할 수는 없습니다.

대상 포인터 유형에 인덱스 부분을 지정하는 비트가 부족하기 때문에 가장 좋은 결과는 잘림입니다.C++ 11은 동일한 정렬 요구 사항을 가진 한 모든 포인터 유형을 reinterpret_cast으로 허용함으로써이 방향으로 끄덕임을 제공합니다. 엄격한 정렬에 의해 "제로화 된"비트는 존재하지 않아도된다.

개체 포인터를 다른 형식의 개체 포인터로 명시 적으로 변환 할 수 있습니다. "T1에 대한 포인터"유형의 값 v가 이 "cv T2 포인터"유형으로 변환되면 T1과 T2가 모두 표준 레이아웃 유형 (3.9) 이고 T2의 정렬 요구 사항이 다음과 같으면 결과는 static_cast<cv T2*>(static_cast<cv void*>(v))입니다. T1,보다 엄격하거나 두 유형 중 하나가 무효 인 경우 "포인터를 T1에 대한 포인터"유형을 "포인터를 T2로"유형으로 변환합니다 (T1 및 T2는 오브젝트 유형이고 T2의 정렬 요구 사항은 이 아니며 원래 유형으로 되돌림). 원래 포인터 값을 산출합니다. 그러한 다른 포인터 포인터의 결과는 지정되지 않습니다.

1

나는 C++과 C 포인터 캐스트가 의미있는 차이가 없다고 생각합니다. this answer에서 나는 예 중 하나만 인용 :

데이터 총장

이클립스 MV 시리즈가 세 가지 구조적 지원 포인터 형식 C 컴파일러에 의해 사용되는 두 개의있는 (워드, 바이트, 비트 포인터) : 바이트 포인터 작업이 돌이킬하고, 문자/단어의 바이트에서 지적 받고있는 그 감각을 잃을 수있는 reinterpret_cast<Word_Aligned_Type*>(char*)을 제안

다른 모든 것들에 대한 char*void*, 워드 포인터합니다.

관련 문제