将 int 打包在一个字符串中

Pack int in a string

本文关键字:一个 字符串 int      更新时间:2023-10-16

我正在尝试将此序列从Python转换为C++。

bytesString = struct.pack('!l', value)

如何使用字节移位将整数值打包到 std::string 中?

易于维护的方法(与字节序无关)

将基元类型的值"编码"为字节序列的典型方法是使用一个简单的std::copy

#include <string>
#include <iostream>
#include <iomanip>
template <typename T>
std::string pack(const T val)
{
   std::string bytes(sizeof(T), '');
   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, '');
   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"

(现场演示)

(我使用 CHAR_BIT 实现可移植性,但硬编码0xFF作为值掩码。您需要修复此问题。

相关文章: