Как я могу преобразовать массив байтов в boost::multiprecision::uint128_t?
Если у меня есть:
char buffer[16];
Как я могу преобразовать его необработанные байты в:
boost::multiprecision::uint128_t
?
Я попытался сделать стандартный бросок в стиле C:
uint128_t myInt = *(uint128_t*)buffer;
хотя это, кажется, не работает должным образом. Также пытался использовать dynamic_cast
Я нашел эту страницу: https://www.boost.org/doc/libs/1_56_0/libs/multiprecision/doc/html/boost_multiprecision/tut/conversions.html
о том, как вести беседы, но, похоже, это не распространяется на подобные вещи. Есть идеи?
РЕДАКТИРОВАТЬ: один из комментариев предложил использовать memcpy (если это было похоже на 128-битный UTC GCC), чтобы скопировать байты в uint128_t. Это, кажется, не работает должным образом, если сделано так, как я ожидал: Я что-то пропустил?
1 ответ
Я нашел способ сделать это, который работает на основе динамической природы типа uint128_t. Кажется, он не использует все 16 байтов для числового значения все время. Он использует их только в том случае, если считает, что они необходимы (вот почему не работает примитивный memcpy()).
Таким образом, хитрость заключается в том, чтобы заставить его думать, что все 16 байтов необходимы, а затем в memcpy() вводить данные. Мы можем сделать это, установив начальное значение -1 (или все Fs):
boost::multiprecision::uint128_t getUintFromBuffer(const std::vector<unsigned char> &buf)
{
boost::multiprecision::uint128_t retU = -1;
memset(&retU, 0, 16);
memcpy(&retU, buf.data(), std::min(buf.size(), (size_t)16));
return retU;
}
int main()
{
std::vector<unsigned char> buf;
buf.resize(16);
buf[0] = 0xaa;
buf[15] = 0xff;
std::cout << std::hex << getUintFromBuffer(buf) << std::endl;
return EXIT_SUCCESS;
}
Запуск этого примера печатает:FF0000000000000000000000000000AA
И это то, что я искал:)
Я хотел бы предложить, что может быть это то, что вы ищете:
#include <boost/multiprecision/cpp_int.hpp>
#include <iostream>
#include <iomanip>
#include <vector>
#include <iterator>
int main()
{
using boost::multiprecision::cpp_int;
// Create a cpp_int with just a couple of bits set:
cpp_int i;
bit_set(i, 5000); // set the 5000'th bit
bit_set(i, 200);
bit_set(i, 50);
// export into 8-bit unsigned values, most significant bit first:
std::vector<unsigned char> v;
export_bits(i, std::back_inserter(v), 8);
// import back again, and check for equality:
cpp_int j;
import_bits(j, v.begin(), v.end());
assert(i == j);
}
Я обнаружил, что просто используя boost::multiprecision::import_bits
работает.
template <unsigned Bits, boost::multiprecision::cpp_integer_type SignType,
boost::multiprecision::cpp_int_check_type Checked>
boost::multiprecision::number<
boost::multiprecision::cpp_int_backend<Bits, Bits, SignType, Checked, void>>
rawToBoost(const void *V) {
using namespace boost::multiprecision;
#if BOOST_ENDIAN_BIG_BYTE
static const auto msv_first = true;
#else
static const auto msv_first = false;
#endif
number<cpp_int_backend<Bits, Bits, SignType, Checked, void>> ret;
auto VPtr = reinterpret_cast<const unsigned char *>(V);
import_bits(ret, VPtr, VPtr + (Bits / 8), 0, msv_first);
return ret;
}
boost::multiprecision::int128_t rawToBoost_int128(const void *V) {
using namespace boost::multiprecision;
return rawToBoost<128, signed_magnitude, unchecked>(V);
}
boost::multiprecision::int128_t rawToBoost_int128_safe(const void *V) {
using namespace boost::multiprecision;
return rawToBoost<128, signed_magnitude, checked>(V);
}
boost::multiprecision::uint128_t rawToBoost_uint128(const void *V) {
using namespace boost::multiprecision;
return rawToBoost<128, unsigned_magnitude, unchecked>(V);
}
boost::multiprecision::uint128_t rawToBoost_uint128_safe(const void *V) {
using namespace boost::multiprecision;
return rawToBoost<128, unsigned_magnitude, checked>(V);
}
Это та же ссылка, на которую ссылался OP (но другая версия повышения).https://www.boost.org/doc/libs/1_62_0/libs/multiprecision/doc/html/boost_multiprecision/tut/ints/cpp_int.html