如何使用多次 memcpy 转换回 std::vector<unsigned char>?

Posted

技术标签:

【中文标题】如何使用多次 memcpy 转换回 std::vector<unsigned char>?【英文标题】:How to use multiple times memcpy to convert back a std::vector<unsigned char>? 【发布时间】:2018-10-11 09:11:40 【问题描述】:

我想在 C++ 中将 stringsdoublestime_t 的一组值转换为 std::vector&lt;unsigned char&gt;。我为此使用memcpy,并在每次我有新值时调用它。我刚刚意识到我必须向后调用它才能在我的向量上以正确的顺序连接。转换所有值后,我想转换回来。我正在做的方式是每次再次调用memcpy 以将原始值转换回来。但是因为第一个之后的值在向量的中间,所以我无法正确地将它转换回来。

如何分别从向量中转换回所有值?我的代码在下面,输出也是。谢谢

int main(void) 
    std::string lat = "lat->";
    double latitude = 13.123456;

    std::vector<unsigned char> result(sizeof(lat) + sizeof(latitude));

    std::cout << "copying to the vector" << std::endl;
    memcpy(result.data(), &latitude, sizeof(latitude)); // add string to the vector
    memcpy(result.data(), &lat, sizeof(result.size()) + sizeof(lat)); // add double to the same vector
    std::cout << "copied to the vector\n" << std::endl;

    std::cout << "printing the vector" << std::endl;
    for (int j = 0; j < result.size(); j++) 
        std::cout << result[j];
    
    std::cout << std::endl;
    std::cout << "printed the vector\n" << std::endl;

    // testing converting back ...................
    std::cout << "printing back the original value" << std::endl;
    double d;
    std::string value;
    // make sure the vector is the right size
    if (result.size() != (sizeof(d) + sizeof(lat)))
        throw std::runtime_error 
                "Size of data in vector and float do not match" ;
    // copy the bytes into the float
    memcpy(&value, result.data(), sizeof(value));
    std::cout << value;
    memcpy(&d, result.data(), sizeof(value) + sizeof(d));
    std::cout << d << std::endl;
    std::cout << "printed back the original value\n" << std::endl;

输出:

copying to the vector
copied to the vector

printing the vector
��(�lat->Pş0��(�
printed the vector

printing back the original value
lat->6.95297e-310
printed back the original value

Segmentation fault (core dumped)

【问题讨论】:

string.data(),不能直接memcpy std::string 您的代码并没有像您认为的那样做任何事情,并且包含许多错误。我强烈建议不要尝试这样的字节操作。对于可能在堆上存储数据的类型(例如 std::string),它们将不可避免地失败。 在c++中你很少需要使用像memcpy这样的低级函数(大多数时候只有当你需要与c apis或接近硬件的apis进行通信时),所以当你使用memcpy时,你应该考虑一下你是否真的做对了。 How to copy std::string into std::vector<char>? @appleapple memcpy 执行字节复制。问题是类型和大小而不是功能。 (尽管出于显而易见的原因你不叫 memcpy) 【参考方案1】:

正如我在 cmets 中所说,除非您知道自己在做什么(您不知道),否则不要做那种事情。

写入内存缓冲区:

std::string lat = "lat->";
double latitude = 13.123456;

std::vector<unsigned char> result(lat.length() + sizeof(latitude));

std::cout << "copying to the vector" << std::endl;
std::memcpy(result.data(), &latitude, sizeof(latitude));             // add double
std::memcpy(result.data()+sizeof(latitude), lat.data(), lat.size()); // add raw string data
std::cout << "copied to the vector\n" << std::endl;

请注意,两次调用传递给memcpy的目标指针是不同的,每次都指向以前未使用的内存。

使用memcpy 回读字符串时需要小心:

double d;
std::string value;
std::memcpy(&d, result.data(), sizeof(latitude));    // copy back the bytes of the double
value.resize(lat.length());
std::memcpy(value.data(),result.data()+sizeof(latitude), value.data(), lat.size());

您看到我们需要知道字符数 (lat.size()) 才能从缓冲区中复制它们。这使得整个方法充其量是有问题的。我强烈建议,在理解了这个例子之后,你不要再做这种事情了。

【讨论】:

我把最后一个memcpy改成了memcpy(value.data(), result.data() + sizeof(latitude), sizeof(value.data()) + lat.size());

以上是关于如何使用多次 memcpy 转换回 std::vector<unsigned char>?的主要内容,如果未能解决你的问题,请参考以下文章

在从 C++ 转换为 C# 的代码中,我应该使用啥来代替 memcpy?

memcpy 仅通过 C++ 复制一个字节

pycuda - memcpy_dtoh,没有给出似乎已设置的内容

单个事务的多次回滚

如何将 Int 转换为 ByteArray,然后使用 Kotlin 将其转换回 Int?

sql在具有回滚的事务中多次插入