2013-04-29 3 views
6

나는 모든 다음 괜찮 할 경우static_cast 무효 * static_cast 무효 대 숯불 * ** 문자 **

char* cp = "abc"; 
void* vp = NULL; 
vp = static_cast<void*>(cp);//ok 
cp = static_cast<char*>(vp);//ok 

그러나 다음이되지 않습니다 :

char** cpp = &cp; 
void** vpp = NULL; 
vpp = static_cast<void**>(cpp);//error C2440: 'static_cast': 
           //cannot convert from 'char **' to 'void **' 
cpp = static_cast<char**>(vpp);//error C2440: 'static_cast': 
           //cannot convert from 'void **' to 'char **' 

누군가가 설명 할 수주십시오 왜 두 번째 예제는 허용되지 않습니다. C++ 표준을 전체 답으로 인용하지 마십시오. 이미 인용 한 답변을 보았 기 때문에 C++ 표준의 의미를 이해할 수 없습니다. 내가 이해하고 싶습니다 두 번째 예제가 작동하지 않습니다 (즉, 큰 도움이 될 위험이있는 예제를 줄 수있는 경우). 왜냐하면 나는 그것을 얻지 못하기 때문입니다. 나에게 두 예제 모두 포인터를 캐스팅하는 것이다. 간접 지정의 추가 수준으로 인해 차이가 나는 이유는 무엇입니까?

+6

암시 적으로 포인터를 'void *'로 변환하고 역방향으로 정적 캐스트 할 수 있습니다. 그러나 이것은 일반적으로 관련이없는'T *'와'U *'에 대해서는 사실이 아닙니다. (이제'T = char *'와'U = void *'를 생각해보십시오.) –

+0

'char **'를'void *'에 캐스팅 할 수 있고 그 반대도 가능합니다. –

+1

@Kerrek SB - 네,하지만 왜 이것이 허용되지 않습니까? 언제 이것이 안전하지 않습니까? – e244

답변

12

void * 포인터가 "anything"을 가리킬 수 있으며 모든 포인터를 void *으로 변환하는 것이 유효하며 모든 포인터를 void *에서 다른 유형으로 변환하는 것이 유효합니다.

그러나 void **void * 값을 가리키는 포인터입니다. 그리고 char **char * 값을 가리키는 포인터입니다. 이러한 유형은 서로 변환 할 수있는 유형을 나타내지 않습니다. 이 작업을 수행해야한다면 void **vpp = reinterpret_cast<void **>(cpp);을 사용할 수 있지만 "안전하지 않습니다"(기본적으로 컴파일러에게 "이봐, 여기 내가 뭘하는지 알기 때문에 그냥해라." 실제로 예상 됨 ...)

+0

"안전하지 않다"에 대한 메모는 –

+0

미안하지만, 아직 이해가 안됩니다. 일부 문자열의 주소가 0x12345678 인 경우이를 char * 또는 void *에 넣을 수 있습니다. 내 char *의 주소가 0x87654321 인 경우 그 값 (주소 0x87654321)을 내 void **에 넣을 수없는 이유는 무엇입니까? 즉.void *에 static_cast 0x12345678을 사용해도 괜찮습니까?하지만 void_cast에 static_cast 0x87654321을 보내 주면 괜찮습니까? 언제/왜 이것이 안전하지 못했을까요? – e244

+0

@ e244 : 문제는 변환이 허용되면 쉽게 형식 시스템을 파괴 할 수 있다는 것입니다. 나는 더 긴 설명을 답으로 제공해 주었지만 짧은 설명은 이중 포인터로 인해 안전하지 않은 방식으로 데이터를 변경할 수 있다는 것입니다. –

6

제한 사항은 유형 시스템이 손상되지 않도록하는 것입니다. 첫 번째 변환은 괜찮 : 당신이 유형을 포기하는 동안

type *p = ...; 
void *vp = p; 

, 당신은하지 void 객체와 함께 할 거의가 있기 때문에하지 않고 원래 값으로 너무 많은 피해를 입힐 수 vp에 대한 모든 변경 포인터에 국한되어 p에 영향을 미치지 않습니다.

는 두 번째의 경우 허용 된 경우 :

type **p = ...; 
void **vp = p; 

그리고 완벽하게보고 정확한 코드는 응용 프로그램을 중단 할 수있다. 예 :

int *parray[10]; 
int **p = parray; 
void **vp = p; 
*vp = new double(); // now parray[0] is a pointer to a double object, 
        // not a pointer to an int!!! 

유형 시스템이 파괴되었습니다.

즉, 두 번째 경우에는 원래 개체를 수정하고 버그를 일으킬 수있는 대상 포인터에 적용 할 수있는 작업이 있습니다. 유사한 사례가 const 다른 사례에서 발견 될 수 있습니다 (int*const int*으로 변환 할 수 있지만 int**const int** ...으로 변환 할 수 없습니다).