2009-08-04 4 views
3

아래 기능에서 reinterpret_cast가 필요한지 궁금합니다. ITER_T는 char *, unsigned char *, std :: vector < 부호없는 char > iterator 또는 이와 비슷한 것일 수 있습니다. 지금까지 해를 끼치 지 않는 것 같지만, 캐스팅은 바이트가 전혀 복사되는 방식에 영향을 미칩니 까?unsigned char *와 char *와의 캐스팅을 다시 해석하십시오.

template<class ITER_T> 
char *copy_binary(
    unsigned char length, 
    const ITER_T& begin) 
{ 
    // alloc_storage() returns a char* 
    unsigned char* stg = reinterpret_cast<unsigned char*>(alloc_storage(length)); 
    std::copy(begin, begin + length, stg); 
    return reinterpret_cast<char*>(stg); 
} 
+2

alloc_storage 함수가 반환하는 유형은 무엇입니까? – zdan

답변

6

reinterpret_casts은 저수준 구현 정의 된 캐스트에 사용됩니다. 표준에 따르면, reinterpret_casts는 다음의 변환 (C++ 03 5.2.10)에 사용할 수 있습니다

  • 정수형 포인터
  • 적분 형 포인터
  • 함수에 대한 포인터로 수 다른 유형의 함수에 대한 포인터로 변환 될 수 있습니다.
  • 오브젝트에 대한 포인터를 다른 유형의 오브젝트에 대한 포인터로 변환 할 수 있습니다.
  • 데이터 멤버에 대한 포인터 또는 포인터는 함수 또는로 변환 될 수 있습니다. 다른 유형의 객체. 이러한 포인터 변환의 결과는 포인터 a가 원래 유형으로 다시 변환된다는 점을 제외하고는 지정되지 않았습니다.
  • 타입 A에 대한 포인터가 reinterpret_cast을 사용하여 명시 적으로 타입 B로 변환 될 수 있으면 타입 A의 표현식을 타입 B에 대한 참조로 변환 할 수 있습니다.

표준으로 지정되지 않은 서로 다른 종류의 캐스팅 이후 char *에서 unsigned char *과 뒷면에 캐스팅하는 대부분의 시스템에서 작동합니다 비록 reinterpret_cast은, 귀하의 경우 좋은 해결책이 아니다 사용하여 말했다. 귀하의 경우에는

나는 static_cast를 사용하거나 유형 char *으로 stg을 정의하여 전혀 캐스팅하지에 대한 생각 :

template<class ITER_T> 
char *copy_binary(
    unsigned char length, 
    const ITER_T& begin) 
{ 
    // alloc_storage() returns a char* 
    char* stg = alloc_storage(length); 
    std::copy(begin, begin + length, stg); 
    return stg; 
} 
+0

+1 나에게 좋은 답변 인 것처럼 보입니다. reinterpret_cast를 사용해야하는 시점을 알려주며 여기서 사용하지 않아야합니다. –

+2

'static_cast'사용에 관한 부분을 제외하고는이 모든 것이 좋습니다. 나의 이해는 정적 캐스트는 관련된 포인터 유형과'void * '사이의 변환에만 사용될 수 있다는 것이다. 'unsigned char'와 'char'는 표준에 따라 관련없는 유형이므로이 경우 reinterpret_cast의 4 번째 글 머리표에서만 다룹니다. –

1

표준에 따라 의도 한대로 작동하고 작성된 코드 4.7 (2), 비록 이것은 2의 보수 표현이있는 기계에서만 보증됩니다.

alloc_storage가 char *를 반환하고 'char'가 서명 된 경우 4.7 (3)을 올바르게 이해하면 반복기의 값 유형이 부호가없는 경우 결과가 구현 정의되고 캐스트를 삭제하고 복사 할 char *.

0

그래서 내가 올바르게 이해한다면, unsigned char에 대한 캐스트는 부호없는 바이트 단위 복사를 보장하는 것입니다. 그러나 그 다음에 당신은 그것을 돌려 보내기 위해 그것을 던져 버립니다. 이 함수는 이런 식으로 설정하기위한 문맥/이유가 정확히 무엇인지 조금 어색해 보입니다. 빠른 수정은이 모든 것을 memcpy()로 대체하는 것일 수도 있습니다 (그러나 주석 된대로 iterator 객체에서는 사용하지 마십시오). 그렇지 않으면 중복 된 캐스트를 제거하십시오.

+1

반복자와 함께 memcpy를 사용할 때는주의해야합니다. 이 경우 그는 벡터를 사용하지만 포함 된 데이터는 항상 인접하지는 않습니다. –

+0

오, 당신은 절대적으로 옳습니다. – nielsj

+0

다음은 컨텍스트입니다. char * 및 substring 범위를 유지하는 StringSlice 클래스로 작업하고 있습니다. 그러나 StringSlice에 보관 된 일부 데이터는 실제로 서명되지 않은 것으로 해석되어야합니다. StringSlice 멤버가있는 클래스는 누군가가 unsigned char 또는 signed char의 여러 가지 방법으로 데이터를 설정할 수있게하고, 데이터를 StringSlice, unsigned char *로 검색하거나 unsigned char의 데이터를 –

1

짧은 대답은 네, 영향을 미칠 수 있습니다.

문자서명 숯불 컨버터블 타입 (C++ 표준 0X n2800에 3.9.1)이다 그래서 당신은 다른 하나의 할당 할 수 있습니다. 캐스트가 전혀 필요하지 않습니다.

[3.9.1] ...문자, 부호있는 문자 및 부호없는 문자는 같은 크기의 저장소 인 을 차지하며 동일한 맞춤을 갖습니다. 요구 사항 : 즉, 그들은 같은 대상 표현을 가지고 있습니다..


[4.7] ...

2 대상 유형 부호 경우, 결과 값 소스 정수 합동 적어도 부호 정수 (인 modulo 2n 여기서, n 은 사용 된 비트 수로 은 부호없는 유형을 나타냅니다.

[참고 : 2의 보수 표현에서, 이 변환은 개념적이며 (잘리는가없는 경우)은 비트 패턴 에는 변화가 없다. -end 참고 ] 대상 유형 서명되면

3, 값이 변하지는 목적지 입력 (비트 필드의 폭)로 표현 될 수 있으면 그렇지 않은 경우 값은 구현에 따라 정의됩니다.

따라서 최악의 경우에도 최상의 (구현이 정의되지 않은) 변환을 얻을 수 있습니다. 어쨌든 대부분의 구현에서 이것은 비트 패턴에서 아무 것도 변경하지 않을 것이며 생성 된 어셈블러를 살펴보면 변환도 수행되지 않습니다.

template<class ITER_T> 
char *copy_binary(unsigned char length, const ITER_T& begin) 
{ 
    char* stg = alloc_storage(length); 
    std::copy(begin, begin + length, stg); 
    return stg; 
} 

컴파일러에 의존하여 reinterpret_cast :

는 [5.2.10.3] reinterpret_cast 의해 수행되는 맵핑은 구현 정의한다. [참고 : 은 원래 값과 다른 표현을 생성 할 수도 있고 생성하지 않을 수도 있습니다. -end note]

참고 : This은 흥미로운 관련 게시물입니다.

관련 문제