在字节数组中嵌入多个整数

Embed multiple ints in byte array

本文关键字:整数 字节 字节数 数组      更新时间:2023-10-16

我正在使用以下代码:

int number; //=smth
unsigned char sendBuffer[255];
sendBuffer[0] = number & 0xFF;
sendBuffer[1] = (number  >> 8) & 0xFF;
sendBuffer[2] = (number  >> 16) & 0xFF;
sendBuffer[3] = (number  >> 24) & 0xFF;

number放入字节数组 sendBuffer 中。

我的问题是:

  1. 假设我现在想在字节数组中嵌入两个数字,我应该这样做吗?

    sendBuffer[0] = number & 0xFF;
    sendBuffer[1] = (number  >> 8) & 0xFF;
    sendBuffer[2] = (number  >> 16) & 0xFF;
    sendBuffer[3] = (number  >> 24) & 0xFF;
    sendBuffer[4] = number2 & 0xFF;
    sendBuffer[5] = (number2  >> 8) & 0xFF;
    sendBuffer[6] = (number2  >> 16) & 0xFF;
    sendBuffer[7] = (number2  >> 24) & 0xFF;
    

    即使大小为 8 或 6 字节,number也能正常工作吗?(我之所以这样说,是因为在某些平台上,int 可能是 4 个字节或 6 个字节,对吧?所以我在想当数字为 6 字节时,上面的代码是否也有效?进一步需要注意的是,即使它是 6 个字节,但我只在其中存储 4 个字节整数,上面的代码会起作用吗?

    这个缓冲区我通常存储在卡的一些内存中,我读回它没有问题(例如,endiannes 等问题,读取时的字节数组似乎按照我保存的顺序出现)。

  2. 最后,如何从字节数组sendBuffer重建整数?

1)是的,像那样继续。不,它仅适用于 4 个字节。

有一种更简单、更好的方法可以做到这一点,尽管如果将缓冲区从一台计算机发送到另一台使用不同体系结构的计算机,可能会导致字节序问题。假设你知道number的类型,在sendBuffer之上叠加另一个数组。

unsigned char sendBuffer[255];
number_type *sendBufferNum = (number_type*) sendBuffer;
sendBufferNum[0] = number;
sendBufferNum[1] = number2;

读取数字可以以相同的方式完成。

unsigned char receiveBuffer[255];
//read values into receiveBuffer
number_type *receiverBufferNum = (number_type*) receiveBuffer;
number_type number = recieveBuffer[0];
number_type number2 = receiveBuffer[1];
  1. 这仅适用于 32 位(4 字节)整数。如果要支持大整数,则必须编写 64 位(8 字节)版本。

  2. 可以使用按位 OR 反转该过程。

    #define BigEndianGetUInt32(ptr)  ( ((uint32)((uint8*)(ptr))[0]) << 24 |   
                                       ((uint32)((uint8*)(ptr))[1]) << 16 |   
                                       ((uint32)((uint8*)(ptr))[2]) <<  8 |   
                                        (uint32)((uint8*)(ptr))[3]) )
    number  = BigEndianGetUInt32(sendBuffer);
    number1 = BigEndianGetUInt32(sendBuffer+4);
    

作为旁注,如果您只是为同一设备序列化数据,则可以将number memcpy sendBuffer .

memcpy(sendBuffer, &number, sizeof(number));
memcpy(sendBuffer+sizeof(number), &number1, sizeof(number1));

即使数字的大小为 8 或 6 个字节,这也能工作吗?

它可以工作,但显然您需要添加更多行来保存值中的所有字节。这是大量的手动工作,可扩展性不强。请改用编程方法

auto num = number;
for (size_t i = 0; i < sizeof(number); i++, num >>= CHAR_BIT)
    sendBuffer[i] = number & 0xFF;

但是,当您已经拥有memcpy()时,为什么要这样做呢?这样您只需要 1 行,甚至更好,它可以轻松地扩展到多个值

memcpy(&sendBuffer[0],               number1, sizeof number1);
memcpy(&sendBuffer[sizeof(number1)], number2, sizeof number2);

最后,如何从字节数组sendBuffer重建整数?

容易。只需将字节移回即可

number  = (sendBuffer[3] << 24) | (sendBuffer[2] << 16) | (sendBuffer[1] << 8) | sendBuffer[0];
number2 = (sendBuffer[7] << 24) | (sendBuffer[6] << 16) | (sendBuffer[5] << 8) | sendBuffer[4];

同样,避免像这样乏味的工作并使用for循环

number = 0;
for (size_t i = 0; i < sizeof(number); i++)
    number = (number << 8) | sendBuffer[i];

memcpy也有效,强烈推荐

memcpy(&number, &sendBuffer[numberIndex], sizeof number);