[英]Convert std::vector<uint8_t> to packed std::vector<uint64_t>
我正在尋找一種有效且無需 UB 的方法將std::vector<uint8_t>
轉換為std::vector<uint64_t>
st std::vector<uint64_t>
::vector<uint64_t> 中的每個元素都包含來自std::vector<uint8_t>
。 其余元素應該用零填充,但可以稍后完成。
到目前為止我想出的最好的方法是:
std::vector<uint64_t> foo(std::vector<uint8_t> const & v8) {
std::vector<uint64_t> v64;
v64.reserve((v8.size() + 7) / 8);
size_t i = 0;
uint64_t tmp;
for(; i + 8 < v8.size(); i += 8) {
memcpy(&tmp, v8.data() + i, 8);
v64.push_back(tmp);
}
tmp = 0; // fill remainder with 0s.
memcpy(&tmp, v8.data() + i, v8.size() - i);
v64.push_back(tmp);
return v64;
}
但我希望有一些更清潔/更好的方法。
Edit1:關於遺漏字節順序問題的解決方案。 @VainMain 指出。
可以在memcpy
之后用字節交換來修復。
如果您打算使用range-v3 library ,您可以使用ranges::view::chunk
(或可能很快可用的 C++23 標准庫實現等價物)。
這將特別減輕您計算將打包值存儲在以下位置所需的向量大小的麻煩:
#include <array>
#include <cstddef>
#include <span>
#include <vector>
#include <range/v3/all.hpp>
std::vector<std::uint64_t> pack(const std::span<const std::uint8_t> values)
{
const auto chunked_view = ranges::view::chunk(values, 8);
std::vector<std::uint64_t> packed(ranges::size(chunked_view));
ranges::transform(chunked_view, packed.begin(), [](const auto& word) {
std::array<std::uint8_t, 8> buf{0}; // init with all 0's
ranges::copy(word, buf.begin());
std::uint64_t packed_word;
std::memcpy(&packed_word, buf.data(), 8);
return packed_word;
});
return packed;
}
示例(參見 godbolt.org )
int main()
{
std::array<uint8_t, 9> values;
std::iota(values.begin(), values.end(), std::uint8_t{0});
for (auto t : pack(values))
std::cout << std::hex << t << std::endl;
// prints
// 706050403020100
// 8
return 0;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.