如何在std :: vector <uint8_t>中存储来自std :: vector <short>的数据

时间:2017-08-21 21:23:51

标签: c++ vector

我想要做的是将数据存储在std::vector<short>的{​​{1}}中,将每个短片分成两个uint8_t值。我需要这样做因为我有一个只发送std::vector<uint8_t>的网络应用程序,所以我需要转换为uint8_t发送,然后在收到uint8_t向量时转换回来。

通常我会做什么(以及我在查看问题时所看到的)是:

std::vector<uint8_t>

但是,如果我理解正确的话,这将取每个单独的短值,截断到uint8_t的大小,并创建一个新数据量和相同数量的条目的向量,当我想要的是相同的包含两倍条目的数据量。

解决方案包括一种扭转过程并尽可能避免复制的方法,这将有很大帮助。谢谢!

5 个答案:

答案 0 :(得分:6)

在8位边界处分割一些东西,你可以使用右移和掩码,即

uint16_t val;
uint8_t low = val & 0xFF;
uint8_t high = (val >> 8) & 0xFF;

现在您可以将您的高点和低点放入订单中的第二个向量中。

答案 1 :(得分:3)

对于拆分和合并,您将拥有以下内容:

unsigned short oldShort;
uint8_t char1 = oldShort & 0xFF; // lower byte
uint8_t char2 = oldShort >> 8; // upper byte

然后将两个部分推到矢量上,并将其发送到您的网络库。在接收端,在重新组装期间,您将读取向量的下两个字节,并将它们组合回短路。

注意:确保接收到的矢量上有偶数个元素,以便在传输过程中不会获得损坏/修改的数据。

// Read off the next two characters and merge them again
unsigned short mergedShort = (char2 << 8) | char1;

答案 2 :(得分:2)

  

我需要这样做是因为我有网络应用程序 1 只能发送std :: vector&#39;

除了屏蔽和位移之外,您还应该在通过网络发送内容时考虑结束。

network 数据表示通常是 big endian 。所以你总是可以把MSB放在第一位。提供简单的功能,如:

std::vector<uint8_t> networkSerialize(const std::vector<uint16_t>& input) {
    std::vector<uint8_t> output;
    output.reserve(input.size() * sizeof(uint16_t)); // Pre-allocate for sake of
                                                     // performance
    for(auto snumber : input) {
        output.push_back((snumber & 0xFF00) >> 8); // Extract the MSB
        output.push_back((snumber & 0xFF)); // Extract the LSB
    }
    return output;
}

并像

一样使用它
std::vector<uint8_t> newVec = networkSerialize(oldvec);

请参阅live demo

1) 强调我的

答案 3 :(得分:1)

免责声明:人们在谈论“网络字节顺序”。如果你发送的信息超过1个字节,当然你需要take network endiannes into account。但是,据我所知,限制“仅发送std::vector<uint8_t>的网络应用程序”明确指出“我不想搞乱那些字节序的东西” uint8_t已经是一个字节,如果你按一个顺序发送一个字节序列,你应该以完全相同的顺序返回它们。这很有用:sending the array through a socket.
在客户端和服务器计算机上可以有不同的系统字节顺序,但是OP没有说明它,所以这是一个不同的故事......

关于答案: 假设所有“endianness”问题都已关闭。 如果你只想发送一个短裤矢量,我相信, VTT 的答案会表现最佳。但是,如果std::vector<short>只是一个特例,您可以使用my answer to a similar question中的pack()函数。它将任何可迭代的容器,字符串,C字符串等包装到一个字节向量中,不执行任何endiannes shenanigans。
只需包含byte_pack.h然后你可以像这样使用它:

#include "byte_pack.h"

void cout_bytes(const std::vector<std::uint8_t>& bytes)
{
    for(unsigned byte : bytes) {
        std::cout << "0x" << std::setfill('0') << std::setw(2) << std::hex
                   << byte << " ";
    }
    std::cout << std::endl;
}


int main()
{
    std::vector<short> test = { (short) 0xaabb, (short) 0xccdd };
    std::vector<std::uint8_t> test_result = pack(test);

    cout_bytes(test_result); // -> 0xbb 0xaa 0xdd 0xcc (remember of endianness)

    return 0;
}

答案 4 :(得分:-1)

只需一次复制所有内容:

::std::vector<short> shorts;
// populate shorts... 
::std::vector<uint8_t> bytes;
::std::size_t const bytes_count(shorts.size() * sizeof(short) / sizeof(uint8_t));
bytes.resize(bytes_count);
::memcpy(bytes.data(), shorts.data(), bytes_count);