私は現在、CBORを実装しています。バイト配列から1,2,4、または8バイトを繰り返し読み込む必要があります.1バイト、2バイト、4バイト、または8バイトの整数型に結合する必要があります。バイト型から整数型へ:ユニオンによるシフト、追加または暗黙の変換?
template<typename T, typename std::enable_if<sizeof(T) == 4, int>::type = 0>
static T get_from_vector(const std::vector<uint8_t>& vec, const size_t current_idx)
{
return static_cast<T>((static_cast<T>(vec[current_idx]) << 030) +
(static_cast<T>(vec[current_idx + 1]) << 020) +
(static_cast<T>(vec[current_idx + 2]) << 010) +
static_cast<T>(vec[current_idx + 3]));
}
:
は、4バイトの場合のために、私は現在、(current_idx
が、私は4バイトの読み取りを開始する場所からのベクトル内の位置をマークし、vec
私はから読んでいたバイトのベクトルである)、このテンプレート関数を使用します
(Iは、それぞれ、1、2の場合のための3つの同様の機能、及び8つのバイトを有する。)
例コールがあろう
std::vector<uint8_t> vec {0x01, 0x00, 0x00, 0xff};
auto num = get_from_vector<uint32_t>(vec, 0);
assert(num == 0x10000FF);
ものの性能がここでの問題ではないようだが、私は次のコードは、より効率的、あるいは少なくともより読みやすいかもしれかどうかそれにもかかわらず、疑問に思う:
template<typename T, typename std::enable_if<sizeof(T) == 4, int>::type = 0>
static T get_from_vector(const std::vector<uint8_t>& vec, const size_t current_idx)
{
union U
{
T result_type;
uint8_t bytes[4];
} u;
u.bytes[3] = vec[current_idx];
u.bytes[2] = vec[current_idx + 1];
u.bytes[1] = vec[current_idx + 2];
u.bytes[0] = vec[current_idx + 3];
return u.result_type;
}
この上の任意の考え?
一般的に動作しますが、それはあなたにとって重要かどうUBは、あるタイプpunningのための組合を使います。別の問題では、それは私が長い間に8進法で見た最初の合理的な使用です;) –
Unionのこの種の使用はUBです@IanM_Matrix1と述べました。しかし、それはほとんどのコンパイラで動作します。もし私が間違っていないとすれば、GCCの文書では、このタイプのUBを例外として扱われるタイプ・ペニングのための組合の使用について明示的に言及しています。 –
ちょうど 'T resultのようなものがあるのはなぜですか? uint8_t * res_ptr = reinterpret_cast(&result); * result ++ = vec [current_idx + 3]; ...? –
akappa