我正在尝试将此序列从Python转换为C ++。
bytesString = struct.pack('!l', value)
如何使用字节移位将整数值打包到std :: string中?
答案 0 :(得分:3)
"编码的典型方法"将原始类型的值转换为字节序列的是简单的std::copy
:
#include <string>
#include <iostream>
#include <iomanip>
template <typename T>
std::string pack(const T val)
{
std::string bytes(sizeof(T), '\0');
std::copy(
reinterpret_cast<const char*>(&val),
reinterpret_cast<const char*>(&val) + sizeof(T),
bytes.begin()
);
return bytes;
}
int main()
{
int x = 42;
std::string bytes{pack(x)};
std::cout << std::noshowbase << std::hex << std::setfill('0');
for (auto c : bytes)
std::cout << "0x" << std::setw(2) << +c << ' ';
// ^ may need tweaking for values above 127; not sure
}
// On my little-endian system with 32-bit int:
// "0x2a 0x00 0x00 0x00"
可能要求C ++ 11严格,因为std::string
在此之前不是正式连续的。我在main
中显然使用了C ++ 11语法,但这可以轻易改变。
如果您希望结果始终处于网络字节顺序(与Python表达式中!
的使用相匹配),则可以先应用htonl
:
std::string bytes{pack(htonl(x))};
(仅reinterpret_cast
整个值(而不是复制)的解决方案存在潜在的对齐和别名问题。)
如果您的代码处于紧凑的循环中并且您不希望使用字节顺序转换和副本,那么您可以考虑转换循环:
#include <string>
#include <climits>
#include <iostream>
#include <iomanip>
template <typename T>
std::string pack_in_network_order(const T val)
{
const size_t NBYTES = sizeof(T);
std::string bytes(NBYTES, '\0');
for (size_t i = 0; i < NBYTES; i++)
bytes[NBYTES - 1 - i] = (val >> (i * CHAR_BIT)) & 0xFF;
return bytes;
}
int main()
{
int x = 42;
std::string bytes{pack_in_network_order(x)};
std::cout << std::noshowbase << std::hex << std::setfill('0');
for (auto c : bytes)
std::cout << "0x" << std::setw(2) << +c << ' ';
}
// On my system with 32-bit int:
// "0x00 0x00 0x00 0x2a"
(我已将[{1}}用于移植性,但使用硬编码CHAR_BIT
作为值掩码。您将要修复此问题。) < / p>