从字节[]到结构的类型转换

Typecasting from byte[] to struct

本文关键字:结构 类型转换 字节      更新时间:2023-10-16

我目前正在进行一个小型C++项目,在该项目中我使用了别人构建的客户端-服务器模型。数据通过网络发送,在我看来,顺序不对。然而,这不是我能改变的。

示例数据流(简化(:

0x20 0x00 (C++: short with value 32)
0x10 0x35 (C++: short with value 13584)
0x61 0x62 0x63 0x00 (char*: abc)
0x01 (bool: true)
0x00 (bool: false)

我可以将此特定流表示为:

struct test {
    short sh1;
    short sh2;
    char abc[4];
    bool bool1;
    bool bool2;
}

我可以用test *t = (test*)stream;进行类型转换。但是,char*的长度可变。然而,它总是以null结尾。

我知道实际上没有办法将流强制转换为结构,但我想知道是否有比struct test() { test(char* data) { ... }}(通过构造函数转换(更好的方法

这被称为封送或序列化。

您必须做的是一次读取一个字节的流(或者将所有数据放在缓冲区中并从中读取(,一旦您有足够的数据用于结构中的成员,就将其填充。

当涉及到字符串时,只需读取,直到达到终止零,然后分配内存,将字符串复制到该缓冲区,并将其分配给结构中的指针。

如果缓冲区中已经有消息,那么以这种方式读取字符串是最简单、最有效的,因为这样就不需要字符串的临时缓冲区。

不过,请记住,使用此方案,当您完成结构时,必须手动释放包含字符串的内存。

只需添加一个成员函数,该函数接受字符缓冲区(函数输入参数char *(并通过解析来填充test结构。
这也使它更加清晰易读。

如果你提供了一个隐式转换构造函数,那么你就会创建一个威胁,它会在你最意想不到的时候进行转换

从字节序列中读取可变长度数据时,你不应该把所有的东西都放在一个单一的结构或变量中。指针也用于存储这个可变长度。

以下建议未经测试:

// data is stored in memory,
// in a different way,
// NOT as sequence of bytes,
// as provided
struct data {
    short sh1;
    short sh2;
    int abclength;
    // a pointer, maybe variable in memory !!!
    char* abc;
    bool bool1;
    bool bool2;
};
// reads a single byte
bool readByte(byte* MyByteBuffer)
{
    // your reading code goes here,
    // character by character, from stream,
    // file, pipe, whatever.
    // The result should be true if not error,
    // false if cannot rea anymore
}
// used for reading several variables,
// with different sizes in bytes
int readBuffer(byte* Buffer, int BufferSize)
{
    int RealCount = 0;
    byte* p = Buffer;
    while (readByte(p) && RealCount <= BufferSize)
    {
        RealCount++
        p++;
    }
    return RealCount;
}
void read()
{
    // real data here:
    data Mydata;
    byte MyByte = 0;
    // long enough, used to read temporally, the variable string
    char temp[64000];
    // fill buffer for string with null values
    memset(temp, '', 64000);
    int RealCount = 0;
    // try read "sh1" field
    RealCount = (readBuffer(&(MyData.sh1), sizeof(short)));
    if (RealCount == sizeof(short))
    {
        // try read "sh2" field
        RealCount = readBuffer(&(MyData.sh2), sizeof(short));       
        if (RealCount == sizeof(short))
        {
            RealCount = readBuffer(temp, 64000);
            if (RealCount > 0)
            {
                // store real bytes count
                MyData.abclength = RealCount;
                // allocate dynamic memory block for variable length data
                MyData.abc = malloc(RealCount);
                // copy data from temporal buffer into data structure plus pointer
                // arrays in "plain c" or "c++" doesn't require the "&" operator for address:
                memcpy(MyData.abc, temp, RealCount);
                // comented should be read as:
                //memcpy(&MyData.abc, &temp, RealCount);
                // continue with rest of data
                RealCount = readBuffer(&(MyData.bool1), sizeof(bool));
                if (RealCount > 0)
                {
                    // continue with rest of data
                    RealCount = readBuffer(&(MyData.bool2), sizeof(bool));
                }
            }
        }
    }
} // void read()

干杯。