在字符串中打包int

时间:2016-02-18 12:51:28

标签: python c++ pack

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

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

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

1 个答案:

答案 0 :(得分:3)

易于维护的方法(不是与endian无关的)

"编码的典型方法"将原始类型的值转换为字节序列的是简单的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"

live demo

可能要求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"

live demo

(我已将[{1}}用于移植性,但使用硬编码CHAR_BIT作为值掩码。您将要修复此问题。) < / p>