例如,
struct Foo
{
Foo(uint8_t b0, uint8_t b1, uint16_t b23)
{
// some code here
}
uint32_t m_n;
};
我可以这样写:
auto dest = reinterpret_cast<uint8_t*>(&m_n);
memcpy(dest, &b0, sizeof(b0));
memcpy(dest + sizeof(b0), &b1, sizeof(b1));
memcpy(dest + sizeof(b0) + sizeof(b1), &b23, sizeof(b23));
但这很丑。以及当有15个此类变量时该怎么办(不要问为什么)
答案 0 :(得分:3)
在显示的特定情况下,您可以使用移位(如注释中所建议)和逻辑或,将给定参数移入目标,这将给出如下代码:
m_n = (b23 << 16) | (b1 << 8) | b0;
但这是非常具体的,您给出的情况。如果您的其他变量具有不同的类型,并且/或者您想复制不同的内容,则必须修改代码以适合每种用途。
另一种方式(使用相同的示例),但是更容易适应不同的目标类型,将是这样的:
uint8_t bytes[4] = { b0, b1, uint8_t(b23 & 0xFF), uint8_t(b23 >> 8) };
memcpy(&m_n, bytes, 4);
首先在其中将字节数组初始化为给定的参数(很容易增加到16个字节),然后使用memcpy
将字节数组移至目标。
可以通过使bytes
成为Foo
的成员并将其值设置在初始值设定项列表中来进一步“优化”后一种方法:
struct Foo
{
Foo(uint8_t b0, uint8_t b1, uint16_t b23) : bytes{ b0, b1, uint8_t(b23 & 0xFF), uint8_t(b23 >> 8) }
{
memcpy(&m_n, bytes, 4);
}
uint8_t bytes[4];
uint32_t m_n;
};
随时要求进一步的澄清和/或解释。
答案 1 :(得分:3)
我怀疑您需要这种功能:
template<typename T>
std::enable_if_t<std::is_integral_v<T>, std::array<uint8_t, sizeof(T)>>
littleEndianBytes(T value)
{
static_assert(sizeof(uint8_t) == 1);
using result_type = std::array<uint8_t, sizeof(T)>;
result_type result;
for(auto& x : result) {
x = value & 0xFF;
value >>= 8;
}
return result;
}
答案 2 :(得分:2)
可能的实现(需要C ++ 17或参见下文):
template<typename T, typename... Ts>
constexpr void combine_as_bits_impl(std::size_t offset, unsigned char* out,
const T& x, const Ts&... xs) {
std::memcpy(out + offset, &x, sizeof(T));
if constexpr (sizeof...(Ts) > 0)
combine_as_bits_impl(offset + sizeof(T), out, xs...);
}
template<typename Out, typename... Ts>
constexpr Out combine_as_bits(const Ts&... xs) {
static_assert((sizeof(Ts) + ...) == sizeof(Out));
unsigned char buff[sizeof(Out)];
combine_as_bits_impl(0, buff, xs...);
Out out;
std::memcpy(&out, buff, sizeof(Out));
return out;
}
用法示例:
auto s = combine_as_bits<std::uint32_t>(
std::uint8_t{0x1}, std::uint8_t{0x2}, std::uint16_t{0x3456});
assert(s == 0x34560201);
和
Foo(std::uint8_t b0, std::uint8_t b1, std::uint16_t b23) :
m_n(combine_as_bits<std::uint32_t>(b0, b1, b23)) {}
如果if constexpr
不可用,则可以使用简单的重载来终止递归:
constexpr void combine_as_bits_impl(std::size_t, unsigned char*) {}
template<typename T, typename... Ts>
constexpr void combine_as_bits_impl(std::size_t offset, unsigned char* out,
const T& x, const Ts&... xs) {
std::memcpy(out + offset, &x, sizeof(T));
combine_as_bits_impl(offset + sizeof(T), out, xs...);
}