C++ 将uint8数组反序列化为int64失败,但应该可以工作

C++ 将uint8数组反序列化为int64失败,但应该可以工作,c++,serialization,deserialization,byte-shifting,C++,Serialization,Deserialization,Byte Shifting,我要通过tcp发送一个int64,需要对它进行序列化和反序列化 首先我把它投给一个uin64 我把它移到一个uint8数组中 然后,我将数组移到uint64中 最后将其转换回int 但它返回的值与我输入的值不同。。。 我已经检查了十六进制值,但它们应该是正确的 代码: 我已经试着解决这个问题一天了,但是我找不到问题 谢谢。尝试使用uint64_t htobe64(uint64_t host_64位)和uint64_t be64toh(uint64_t big_endian_64位)函数分别从主机

我要通过tcp发送一个int64,需要对它进行序列化和反序列化

首先我把它投给一个uin64

我把它移到一个uint8数组中

然后,我将数组移到uint64中

最后将其转换回int

但它返回的值与我输入的值不同。。。 我已经检查了十六进制值,但它们应该是正确的

代码:

我已经试着解决这个问题一天了,但是我找不到问题


谢谢。

尝试使用uint64_t htobe64(uint64_t host_64位)和uint64_t be64toh(uint64_t big_endian_64位)函数分别从主机转换为big endian(网络顺序)和从网络顺序转换为主机顺序

您正在移动整个值。尝试以下方法:

(bytes[0] << 56) | 
(bytes[1] << 48) |
...  (bytes[7])

(bytes[0]尝试使用uint64\u t htobe64(uint64\u t host\u 64位)和uint64\u t be64toh(uint64\u t big\u endian\u 64位)函数分别从主机转换为big endian(网络顺序)和从网络顺序转换为主机顺序

您正在移动整个值。请尝试以下操作:

(bytes[0] << 56) | 
(bytes[1] << 48) |
...  (bytes[7])

(bytes[0]如果在具有相同endianness的计算机之间传输数据,则不需要逐字节序列化数据,只需发送内存中表示的数据即可。在这种情况下,您不需要任何类似的内容,只需像这样使用memcpy调用即可:

// Serialize
memcpy(&bytes, &val, sizeof(val));

// Deserialize
int64_t val2;
memcpy(&val2, &bytes, sizeof(val));
如果您在不同终端的主机之间发送数据,您应该按照Roger的aswer中找到的方式发送数据,基本上您必须确保数据在两端以相同的方式表示

这里有一个变体,它不仅可以序列化,而且可以在任何平台上使用任何类型的int

#include <iostream>
#include <type_traits>

using namespace std;

template <typename T> enable_if_t<is_integral_v<T>> serialize(T t, char *buf)
{
    for(auto i = 0U; i < sizeof(t); ++i) {
        buf[i] = t & 0xff;
        t >>= 8;
    }
}

template <typename T> enable_if_t<is_integral_v<T>> deserialize(T &t, char const *buf)
{
    for(auto i = 0U; i < sizeof(t); ++i) {
        t <<= 8;
        t |= buf[sizeof(t) - 1 - i];
    }
}

int main() {
    int64_t t1 = 0x12345678;

    int64_t t2{0};

    char buffer[sizeof(t1)];
    serialize(t1, buffer);

    deserialize(t2, buffer);

    cout << "I got " << hex << t2 << endl;
}
#包括
#包括
使用名称空间std;
如果序列化,则启用模板(t,char*buf)
{
对于(自动i=0U;i>=8;
}
}
反序列化时启用模板(t&t,字符常量*buf)
{
对于(自动i=0U;it如果要在具有相同endiance的机器之间传输数据,则不需要逐字节序列化数据,只需发送内存中表示的数据即可。在这种情况下,不需要类似的任何内容,只需使用memcpy调用,如下所示:

// Serialize
memcpy(&bytes, &val, sizeof(val));

// Deserialize
int64_t val2;
memcpy(&val2, &bytes, sizeof(val));
如果您在不同终端的主机之间发送数据,您应该按照Roger的aswer中找到的方式发送数据,基本上您必须确保数据在两端以相同的方式表示

这里有一个变体,它不仅可以序列化,而且可以在任何平台上使用任何类型的int

#include <iostream>
#include <type_traits>

using namespace std;

template <typename T> enable_if_t<is_integral_v<T>> serialize(T t, char *buf)
{
    for(auto i = 0U; i < sizeof(t); ++i) {
        buf[i] = t & 0xff;
        t >>= 8;
    }
}

template <typename T> enable_if_t<is_integral_v<T>> deserialize(T &t, char const *buf)
{
    for(auto i = 0U; i < sizeof(t); ++i) {
        t <<= 8;
        t |= buf[sizeof(t) - 1 - i];
    }
}

int main() {
    int64_t t1 = 0x12345678;

    int64_t t2{0};

    char buffer[sizeof(t1)];
    serialize(t1, buffer);

    deserialize(t2, buffer);

    cout << "I got " << hex << t2 << endl;
}
#包括
#包括
使用名称空间std;
如果序列化,则启用模板(t,char*buf)
{
对于(自动i=0U;i>=8;
}
}
反序列化时启用模板(t&t,字符常量*buf)
{
对于(自动i=0U;iint64字节测试点64(uint8字节[8])
{
uint64_t v=0;
v |=字节[0];v
int64字节测试点64(uint8字节[8])
{
uint64_t v=0;

v |=字节[0];v这应该可以工作。您可能还需要检查ByTestPoint64函数中的输入数组大小是否正确

std::array<uint8_t, 8> int64ToBytes(int64_t val)
{
    uint64_t v = (uint64_t)val;
    std::array<uint8_t, 8> bytes;
    for (size_t i = 0; i < 8; i++)
    {
        bytes[i] = (v >> (8 * (7 - i))) & 0xFF;
    }
    return bytes;
}

int64_t bytesToInt64(uint8_t bytes[8])
{
    uint64_t v = 0;
    for (size_t i = 0; i < 8; i++)
    {
        v |= (bytes[i] << (8 * (7 - i)));
    }
    return (int64_t)v;
}
std::数组int64ToBytes(int64\u t val)
{
uint64_t v=(uint64_t)val;
std::数组字节;
对于(大小i=0;i<8;i++)
{
字节[i]=(v>>(8*(7-i))&0xFF;
}
返回字节;
}
int64字节测试点64(uint8字节[8])
{
uint64_t v=0;
对于(大小i=0;i<8;i++)
{

v |=(bytes[i]这应该可以工作。您可能还需要检查ByTestPoint64函数中的输入数组大小是否正确

std::array<uint8_t, 8> int64ToBytes(int64_t val)
{
    uint64_t v = (uint64_t)val;
    std::array<uint8_t, 8> bytes;
    for (size_t i = 0; i < 8; i++)
    {
        bytes[i] = (v >> (8 * (7 - i))) & 0xFF;
    }
    return bytes;
}

int64_t bytesToInt64(uint8_t bytes[8])
{
    uint64_t v = 0;
    for (size_t i = 0; i < 8; i++)
    {
        v |= (bytes[i] << (8 * (7 - i)));
    }
    return (int64_t)v;
}
std::数组int64ToBytes(int64\u t val)
{
uint64_t v=(uint64_t)val;
std::数组字节;
对于(大小i=0;i<8;i++)
{
字节[i]=(v>>(8*(7-i))&0xFF;
}
返回字节;
}
int64字节测试点64(uint8字节[8])
{
uint64_t v=0;
对于(大小i=0;i<8;i++)
{

v |=(字节[i]我不知道我可能会把接收软件放在哪台机器上,所以我序列化它只是为了确定^^我不知道我可能会把接收软件放在哪台机器上,所以我序列化它只是为了确定^^疯狂的我看了这么长时间的代码,却没有注意到疯狂的我看了这么长时间的代码时间和未注意到,在ByTestPoint64函数中,您缺少字节[2]索引,因此反向函数与转换函数不同。如果您更正了索引,您的函数可能会正常工作。在ByTestPoint64函数中,您缺少字节[2]索引,因此反向函数与转换函数不同。如果您更正了索引,您的函数可能会很好地工作。