【问题标题】:How to convert vector<unsigned char> to int?如何将 vector<unsigned char> 转换为 int?
【发布时间】:2010-10-27 09:00:53
【问题描述】:

我有vector&lt;unsigned char&gt; 提交了二进制数据。比如说,我需要从向量(2 个字节)中取出 2 个项目并将其转换为整数。不用 C 风格怎么能做到这一点?

【问题讨论】:

  • “C-style”是最好的方法,因为你要重新解释不同类型的数据,你为什么害怕呢?
  • @CharlesB:在罗马时,像罗马人那样做。这是 C++,使用 C++ 强制转换运算符是明智的。

标签: c++ stl stdvector


【解决方案1】:

请使用移位运算符/按位运算。

int t = (v[0] << 8) | v[1];

此处提出的所有基于强制转换/联合的解决方案都是 AFAIK 未定义行为,并且可能在利用 strict aliasing(例如 GCC)的编译器上失败。

【讨论】:

  • 如果我错了,请纠正我,但由于v[0] 是一个无符号字符,如果我们之前不将&lt;&lt; 8 转换为int&lt;&lt; 8 不会生成警告吗?
  • 小于int 的类型在与算术或按位运算符一起使用时会被提升为 int,因此移位工作正常,无需显式转换 v[0]。
  • 您能解释一下这是如何工作的吗?移位操作中的8有什么意义?如果我将它用于 long long 类型而不是 int 类型,这个表达式会如何变化?
  • @TheMitraBoy -- 它将 v[0] 移动到正确的小数位,然后添加 v[1]。因此,如果您有 0x12、0x34,您将得到 0x1234。万一你还在想 XD
【解决方案2】:

你可以这样做:

vector<unsigned char> somevector;
// Suppose it is initialized and big enough to hold a uint16_t

int i = *reinterpret_cast<const uint16_t*>(&somevector[0]);
// But you must be sure of the byte order

// or
int i2 = (static_cast<int>(somevector[0]) << 8) | somevector[1];
// But you must be sure of the byte order as well

【讨论】:

  • 您可以使用 ntohs() 使其独立于大/小端
  • 在某些平台上,如果您尝试在奇数偏移处执行此操作,第一个版本将生成异常。在许多(包括大多数现代英特尔,我认为)上,奇数偏移将涉及性能损失。如果性能至关重要,则由程序员决定更快的方式。
  • 说实话,reinterpret_cast 比位运算更“C 风格”,它只是被 C++ 模板隐藏了! ;) 关于粪便的表达是什么? ;) 我总是使用按位运算,坦率地说,它更清晰!
【解决方案3】:

v[0]*0x100+v[1]

【讨论】:

  • 如果我们说的是小端序,反之亦然。
  • 行不通。 v[0] 是一个无符号字符。您必须首先将其转换为整数,这样* 0x100 才不会溢出。
  • v[0] 将被隐式提升为有符号整数。 C 标准第 3.2.1.1 节。
  • 这一定比 C++ 更多吗?无论如何,它是按位运算的次优版本(即编译器最有可能对按位运算进行优化)!如果 OP 是在一个类之后(类似于 Java nio 中的 ByteBuffer),那是一个不同的问题......
  • @user434507,这与分数无关,我只是想向您强调,您不应该仅仅因为它被认为是“C 风格”而忽略该语言的一部分。 . 如果你明确地在一个类之后从二进制流中正确序列化/反序列化数据,请查看 boost 的序列化库 - 它非常强大。
【解决方案4】:

好吧,另一种方法是包装对 memcpy 的调用:

#include <vector>
using namespace std;

template <typename T>
T extract(const vector<unsigned char> &v, int pos)
{
  T value;
  memcpy(&value, &v[pos], sizeof(T));
  return value;
}

int main()
{
  vector<unsigned char> v;
  //Simulate that we have read a binary file.
  //Add some binary data to v.
  v.push_back(2);
  v.push_back(1);
  //00000001 00000010 == 258

  int a = extract<__int16>(v,0); //a==258
  int b = extract<short>(v,0); //b==258

  //add 2 more to simulate extraction of a 4 byte int.
  v.push_back(0);
  v.push_back(0);
  int c = extract<int>(v,0); //c == 258

  //Get the last two elements.
  int d = extract<short>(v,2); // d==0

  return 0;
}

extract 函数模板也适用于 double、long int、float 等。

此示例中没有尺寸检查。我们假设 v 在每次调用 extract 之前实际上有足够的元素。

祝你好运!

【讨论】:

    【解决方案5】:

    “不是 C 风格”是什么意思?使用按位运算(移位和或)来使其工作并不意味着它是“C 风格!”

    怎么了:int t = v[0]; t = (t &lt;&lt; 8) | v[1];

    【讨论】:

      【解决方案6】:

      如果你不想关心大/小端,你可以使用:

      vector<unsigned char> somevector;
      // Suppose it is initialized and big enough to hold a uint16_t
      
      int i = ntohs(*reinterpret_cast<const uint16_t*>(&somevector[0]));
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-09-01
        • 2011-12-15
        • 1970-01-01
        相关资源
        最近更新 更多