2009-07-28 3 views
0

가능한 중복 :
Should I use static_cast or reinterpret_cast when casting a void* to whateverstatic_cast와 reinterpret_cast의 효과가 같을 때 사용할 수있는 것은?

종종는 Win32는 다른 하나 개의 불투명 한 유형에서 캐스팅하는 데 필요한 프로그래밍 특히에서. 예를 들어 :

HFONT font = cast_here<HFONT>(::GetStockObject(SYSTEM_FONT)); 

static_cast와 reinterpret_cast 모두 여기에 적용하고 HFONT 특별히 GetStockObject (에 의해 반환 HFONT 및 HGDIOBJ을 정의 도입 구조체 더미에 대한 포인터이기 때문에 정확히 같은 효과) 무효 * 포인터가 있습니다.

static_cast 또는 reinterpret_cast 중 어느 것이 더 좋습니까?

+1

Dupe : http://stackoverflow.com/questions/310451 –

답변

2

모두> < reinterpret_cast 것은 더욱 위험하다 주목했다 static_cast보다 <>.
reinterpret_cast <>은 모든 유형 정보를 무시하고 실제 처리없이 새로운 유형을 할당하기 때문에 처리가 완료됩니다 (일반적으로 포인터의 비트 패턴은 같지만).

누구나 언급하지 못한 것은 reinterpret_cast <>가 프로그램을 문서화하는 수단입니다. 이 코드는 우리가 무언가를 손상시켜야하는 코드를 읽는 사람에게 알려줍니다. 결과적으로 위험한 캐스트로 끝났습니다.이 코드를 엉망으로 만들 때 조심하십시오.

reinterpret_cast <>을 사용하면 코드에서 위험한 부분을 강조 표시 할 수 있습니다.

무효에서 캐스트하는 경우 * 캐스트 할 작업에 대한 정보를 입력하지 않습니다.
잘못된 캐스트 또는 이전에 void *로 변환 된 원래 유형으로 캐스트를 수행 중입니다. 다른 유형의 주조는 정의되지 않은 동작으로 끝날 것입니다.

reinterpret_cast <>을 사용하면 reinterpret_cast <>을 사용하여 void *에 대한 포인터를 캐스팅하여 원래 유형으로 되돌릴 수 있다는 것을 표준으로 보장하는 것이 가장 이상적입니다. 그리고 reinterpret_cast <을 사용함으로써 당신은 나중에 따라 오는 인간들에게 뭔가 나쁜 일이 일어나고 있다고 지적하고 있습니다.

+1

일부 카운터 포인트 (Shmoopty가 지적한) 체크 아웃에 대해서는 이전 질문 인 http://stackoverflow.com/questions/310451을 참조하십시오. static_cast에 대한 요점은 더 제한적이어서 위험한 상황에서도 잠재적으로 버그를 찾습니다. –

+0

@ 리차드 : 형식 정보가 없을 때 어떻게 버그를 찾을 수 있습니까? void *는 유형이 가질 수있는 정보가 거의 없습니다. 또한 지정한 기사에서 답변의 주석은 알고있는 유형 (T *)에서 다른 알려진 유형 (U *)으로 void *를 통해 유형 변환을 처리합니다. 이 상황에서 나는 reinterpret_cast를 사용하면 안된다는 것에 전적으로 동의한다. 그러나 (T *)에서 void * back to (T *) 로의 캐스팅은 reinterpret_cast를위한 것입니다. –

+0

@Martin : reinterpret_cast를 사용하여 변환 할 수있는 포인터 유형 세트가 static_cast를 사용하는 세트보다 큽니다. 일부 코드를 수정하여 형식이 'void *'가 더 이상 to 형식이 아니게 변경된 경우 reinterpret_cast의 경우 코드가 자동으로 계속 컴파일되지만 (정의되지 않은 동작이 있음) static_cast의 경우 코드는 comiple 오류가 발생합니다. IMHO, 후자가 바람직합니다. –

12

static_cast이 항상 바람직합니다. 절대적으로 필요한 경우가 아니면 reinterpret_cast을 수행하지 마십시오.

reinterpret_cast은 형식이 가장 안전한 캐스팅입니다.

더 자세한 정보는 this website에서 언제 어떤 캐스트를 사용해야하는지에 대해 설명합니다.

+7

저는 이런 종류의 담요 진술을 싫어합니다. 사실이 아닙니다. static_cast는 캐스트를 사용할 때만 사용하는 것이 바람직합니다. reinterpret_cast는 모든 위험한 캐스트에 사용해야하므로 코드에서 신속하게 찾을 수 있습니다. 두 개의 포인터 유형 사이에 캐스트 (관련이없는 경우)는 reinterpret_cast 조작입니다. 관계가 있다면 static_cast가 더 적절할 수 있습니다. 이 quetion의 문맥에서 당신은 void *에서 캐스팅 할 때 reinterpret_cast를 사용할 것입니다. reinterpret_cast를 사용하면 이것이 잠재적으로 위험한 캐스트임을 알 수있는 좋은 방법입니다. –

+1

그래, 어떤 캐스트가 static_cast를 사용하면 안전하지 않은가? static_cast <>는 일종의 정의 된 의미를 갖는 캐스트 용이며, 보통 합리적으로 안전합니다. –

2

static_cast가 선호됩니다.

스콧 마이어스

의해보다 효과적인 C++에서이 오퍼레이터 [reinterpret_cast] 형에게 그 결과 거의 항상 구현 정의 변환을 수행하는데 사용된다. 결과로 reinterpret_casts는 거의 휴대용입니다.

reinterpret_cast의 가장 일반적인 용도는 함수 포인터 유형간에 변환하는 것입니다.

+0

포인터를 void *로 캐스팅 한 다음 동일한 포인터 유형으로 다시 캐스팅하는 것은 reinterpret_cast를 사용하기위한 표준에 의해 보장받습니다. 그래서이 시점은 실제로 유지되지 않습니다. –

+0

하지만 일반적인 경우에는 static_cast <>가 좋습니다. –

3

reinterpret_cast는 구현이 정의되어 있으므로 내 경험적 규칙은 "static_cast 내가 할 수있는 곳, 필요한 곳에서 reinterpret_cast"입니다.

(다른 캐스트는 제외)

2

static_cast가 바람직하다고 생각합니다. 여기에 대해서도 더 많은 논의가있는 another stack overflow post이 있습니다.

15

캐스트가 똑같은 효과를 나타낼 것이라고 말하는 것은 정확하지 않습니다.

  • static_cast<T>(x)T를 입력 표현 x 변환 말한다 캐스트는 두 개의 완전히 다른 일을.
  • reinterpret_cast<T*>(&x)

생각 해보자 T의 *와 같은 메모리 위치 '& X'를 해석 말한다 다음

struct A1 { int a1; }; 
struct A2 { int a2; }; 
struct B : public A1, public A2 {}; 

void foo (A1 * a1, A2 * a2) 
{ 
    B * b1_a1 = static_cast<B*> (a1); 
    B * b2_a1 = reinterpret_cast<B*> (a1); 
    B * b1_a2 = static_cast<B*> (a2); 
    B * b2_a2 = reinterpret_cast<B*> (a2); 

    std::cout << "b1_a1==b1_a2" << (b1_a1==b1_a2) << std::endl; 
    std::cout << "b2_a1==b2_a2" << (b2_a1==b2_a2) << std::endl; 
} 

int main() 
{ 
    B b; 
    foo (&b, &b); 
} 

이 프로그램은 다음과 같은 출력 결과 :

g++ -o t t.cc ; ./t 
b1_a1==b1_a2: 1 
b2_a1==b2_a2: 0 

이를 표시 방법은 static_cast에서 a2 ~ b2 c 정확하게 b의 시작을 가리 키도록 포인터를 올바르게 조정했지만 reinterpret_cast은 그렇지 않습니다.

+0

이것은 훌륭한 예입니다. – quark

+0

네,하지만 질문은 void *에서 캐스팅하는 것이 었습니다. 또한 static_cast <>에서는 캐스팅 다운이 정상이지만 캐스팅 업 (기본 클래스에서 멀어짐)하면 dynamic_cast <>를 사용하는 것이 더 적합 할 것이라고 언급 함 <> –

+0

@Martin : 질문 제목은 캐스트가 동일한 동작을하는 경우 . 세부 사항에서는 이러한 상황의 예로 '무효'사례를 사용할 수 있지만 이것이이 질문의 주된 동기라면 http://stackoverflow.com/questions/310451의 정확한 사본으로 마감해야합니다. –

0

내 일반 조언 :

reinterpret_cast<>는 최후의 수단으로 만 사용됩니다. 컴파일러에게 모든 안전성을 버리고, '모든 안전함 제거'라고 말하고, 컴파일러가 코드에 대해 알고있는 것과 상관없이 실제로는 괜찮다고 말합니다. 그 밖의 기능은 작동하지 않을 때만 사용해야합니다.

동일한 효과가있는 곳이 있습니다. IF 코드가 올바르게 표시됩니다. 결국 변경하고 실수를 범하고 캐스팅이 올바르지 않으면 static_cast<>이 아마도 캐치 할 것이지만 reinterpret_cast<>은 확실히 캐치하지 않습니다.

이 특별한 시나리오에서 마지막 인수는 그다지 중요하지 않습니다. API가 의미를 부과합니다. 그들은 잘 이해 된 의미론이다; 그리고 당신은 (void *)를 캐스팅하고 있습니다.

그럼에도 불구하고, 나는 static_cast<>을 사용하고 정말로 특별한 상황이 유형의 안전을 무시하는 저를 강제로 장소를 reinterpret_cast<> 떠날 것이다. 이것은 API의 C 호환 특성으로 인해 필요한 "일반적인"형변환입니다.

(< static_cast 차이점에 대한 자세한 내용은도 my post here 참조>과 reinterpret_cast <>)

1

실제로해야 할 일은 무엇이든해야합니다. 그게 가장 가능성이 높고 앞으로 호환 될 가능성이 가장 높습니다. 저자가 완전히 우둔한 경우가 아니면.

업데이트 : 찾아 보았습니다. Win32 문서는 C 스타일 캐스트를 사용합니다. 이 경우 C++은 static cast을 수행하는 C 스타일 캐스트를 정의합니다. 올바른 대답은 static_cast입니다. 또는 C 스타일의 캐스트이지만 일반적으로 가장 잘 사용됩니다.

+1

MSDN이 C 개발자를 위해서도 inetnded된다는 것은 기억해야 할 가치가 있습니다. 이것이 C 캐스트를 사용하는 이유 일 수 있습니다. MSDN은 종종 유해한 것으로 간주되는 헝가리 표기법을 사용합니다. 그래서 나는 MSDN이하는 일이기 때문에 무언가를하지 않을 것입니다. – sharptooth

+0

그게 유례가있는 것은 아닙니다. 사용하는 변수 이름은 인터페이스와 아무 관련이 없기 때문에 당신에게 달려 있습니다 (물론 매크로에 사용하는 이름을 피하는 것 제외). 그러나 당신은 그들이 사용하는 캐스트와 호환되는 방식으로 캐스트해야합니다. 분명히, 나는 단지 일반적인 경우가 아니라 win32 함수의 반환 값에 대해서만 이야기 할뿐입니다. –

관련 문제