std :: array를 사용하는 std :: bit_cast 말했다 그 std::bit_cast비트가

그의 최근 강연에서 “현대 C의 유형 말장난 ++” 티무르 Doumler는 말했다std::bit_cast비트가 캐스팅에 사용할 수 없습니다 floatunsigned char[4]C 스타일 배열은 함수에서 반환 할 수 없기 때문에. 우리는 std::memcpy비슷한 것을 reinterpret_cast<unsigned char*>(&f)[i]잘 정의 할 때 C ++ 23 (또는 그 이후 버전)을 사용 하거나 기다려야 합니다.

C ++ 20에서 우리가 사용할 수 std::array와 함께 std::bit_cast,

float f = /* some value */;
auto bits = std::bit_cast<std::array<unsigned char, sizeof(float)>>(f);

C 스타일의 배열 대신에 float?



답변

예, 이것은 모든 주요 컴파일러에서 작동하며 표준을 살펴보면 이식성이 뛰어나고 작동합니다.

우선 std::array<unsigned char, sizeof(float)>집계 ( https://eel.is/c++draft/array#overview-2 ) 가 보장됩니다 . 이것으로부터 내부에 정확히 sizeof(float)많은 숫자가 char들어 char[]갑니다 (일반적으로 a 는 afaics 표준은이 특정 구현을 요구하지 않지만 요소는 연속적이어야한다고 말하지만) 추가 비 정적 멤버를 가질 수 없습니다.

따라서 사소한 복사가 가능하며 크기도 float동일합니다.

이 두 속성을 사용하면 둘 bit_cast사이에있을 수 있습니다.


답변

정렬 및 패딩 문제를 고려하지 않았으므로 허용 된 답변이 잘못되었습니다.

[배열] / 1-3 당 :

헤더 <array>는 고정 크기의 객체 시퀀스를 저장하기위한 클래스 템플릿을 정의합니다. 배열은 연속 컨테이너입니다. 인스턴스의 array<T, N>저장 N형태의 소자는 T, 그래서 그것은 size() == N불변이다.

배열은 N
유형을로 변환 할 수있는 최대 요소 까지 목록으로 초기화 할 수있는 집계입니다 T.

배열 [container.requirements]은 기본 생성 된 배열 객체가 비어 있지 않고 스왑에 일정한 복잡성이 없다는 점을 제외하고 컨테이너 및 가역 컨테이너 ( ) 의 모든 요구 사항을 충족합니다 . 배열은 시퀀스 컨테이너의 일부 요구 사항을 충족합니다. 여기에서는 이러한 테이블 중 하나에 설명되지 않은 배열에 대한 조작과 추가 의미 정보가있는 조작에 대해서만 설명합니다.

표준은 실제로 std::array정확히 하나의 공개 데이터 멤버를 가질 필요가 없으므로 T[N]이론 상으로는 sizeof(To) != sizeof(From)또는 가능합니다 is_­trivially_­copyable_­v<To>.

그래도 이것이 실제로 작동하지 않으면 놀랄 것입니다.


답변

예.

에 따라 종이 의 동작을 설명 std::bit_cast하고, 그 제안 구현 까지 두 가지 유형이 같은 크기를 가지고만큼 하찮게 캐스트가 성공해야 복사 가능한.

단순화 된 구현은 std::bit_cast다음과 같아야합니다.

template <class Dest, class Source>
inline Dest bit_cast(Source const &source) {
    static_assert(sizeof(Dest) == sizeof(Source));
    static_assert(std::is_trivially_copyable<Dest>::value);
    static_assert(std::is_trivially_copyable<Source>::value);

    Dest dest;
    std::memcpy(&dest, &source, sizeof(dest));
    return dest;
}

모든 주장 unsigned charsize_of(float)관련 하여 float (4 바이트) 및 배열이므로 기본 std::memcpy이 수행됩니다. 따라서 결과 배열의 각 요소는 float의 연속 된 1 바이트입니다.

이 동작을 증명하기 위해 컴파일러 탐색기에서 https://godbolt.org/z/4G21zS에서 시도 할 수있는 작은 예제를 작성했습니다 . float 5.0은 Big EndianOx40a00000 에서 해당 float 숫자의 16 진수 표현에 해당하는 바이트 배열 ( ) 로 올바르게 저장됩니다 .


답변