想要将字符数组的部分转换/类型转换为值

Want to translate/typecast parts of a char array into values

本文关键字:转换 类型转换 字符 数组      更新时间:2023-10-16

我正在使用网络,在将大量数据的数据包转换为我想要的值时遇到了一点障碍。

基本上,我已经做了一个我希望我的包看起来有点的模型包。本质上是一个Char(8位值),指示消息是什么,由switch语句检测,然后根据8位值之后的数据填充值。我希望我的包里有各种各样的信息,这些信息可能是不顺序的。

例如,我可能以结尾的心跳结束,或者是聊天消息中的一串文本,等等。

我只是想对我的程序说,从char数组中的某个点获取数据,并将它们类型转换(如果这是术语的话?)成我想要的样子。有什么好的简单方法可以做到这一点?

char bufferIncoming[15];
ZeroMemory(bufferIncoming,15);
//Making a mock packet
bufferIncoming[0] = 0x01; //Heartbeat value
bufferIncoming[1] = 0x01; //Heartbeat again just cause I can
bufferIncoming[2] = 0x10; //This should = 16 if its just an 8bit number, 
bufferIncoming[3] = 0x00; // This
bufferIncoming[4] = 0x00; // and this
bufferIncoming[5] = 0x00; // and this
bufferIncoming[6] = 0x09; // and this should equal "9" of its is a 32bit number (int)
bufferIncoming[7] = 0x00;
bufferIncoming[8] = 0x00;
bufferIncoming[9] = 0x01;
bufferIncoming[10] = 0x00; //These 4 should be 256 I think when combines into an unsigned int
//End of mockup packet

int bufferSize = 15; //Just an arbitrary value for now
int i = 0;
while (i < bufferSize)
{
    switch (bufferIncoming[i])
    {
        case 0x01: //Heart Beat
            {
                cout << "Heartbeat ";
            }
            break;
        case 0x10: //Player Data
            {
                //We've detected the byte that indicates the following 8 bytes will be player data. In this case a X and Y position
                playerPosition.X = ??????????; //How do I combine the 4 hex values for this?
                playerPosition.Y = ??????????;
            }
            break;
        default:
            {
                cout << ".";
            }
            break;
    }
    i++;
}
cout << " End of Packetn";


根据Clairvoire的想法,我添加了以下内容:

playerPosition.X = long(bufferIncoming[3]) << 24 | long(bufferIncoming[4]) << 16 | long(bufferIncoming[5]) << 8 | long(bufferIncoming[6]);

注意我改变了周围的移位值

另一个重要的变化是

unsigned char bufferIncoming[15]

如果我不这样做,我得到的是与每个元素的组合混合在一起的负值。我不知道编译器在做什么,但是它真的很烦人。

你可以想象这不是我喜欢的解决方案,但我要试一试。"Chad"有一个很好的例子,说明我可以如何构建它,工作中的一个程序员同事也推荐了他的实现。但是…

我有一种感觉,一定有一种更快更干净的方法来做我想做的事。我试过……

playerPosition.X = *(bufferIncoming + 4) //Only giving me the value of the one hex value, not the combined >_<
playerPosition.X = reinterpret_cast<unsigned long>(&bufferIncoming); //Some random number that I dont know what it was

. .还有一些我删掉的东西,它们也不管用。我期望做的是指向字符缓冲区的某个地方,说"嘿,playerPosition,开始从这个位置读取,并根据字节数据填写你的值"。

例如…

playerPosition = (playerPosition)bufferIncoming[5]; //Reads from this spot and fills in the 8 bytes worth of data
//or
playerPosition.Y = (playerPosition)bufferIncoming[9]; //Reads in the 4 bytes of values

…为什么它不像那样工作,或者类似的东西?

可能有一个漂亮的版本,但我个人会使用左移和or组合四个字符变量,像这样:

playerPosition.X = long(buffer[0]) | long(buffer[1])<<8 | long(buffer[2])<<16 | long(buffer[3])<<24;

序不应该是一个问题,因为按位逻辑总是执行相同的顺序,最低的顺序在右边(就像小数的个位在右边)

编辑:Endianness可能会成为一个因素,这取决于发送机器在通过网络发送整数之前如何初始分割整数。如果它不以与使用移位重新组合整数相同的方式分解整数,那么您可能会得到一个第一个字节是最后一个字节,最后一个字节是第一个字节的值。像这样的小歧义促使大多数人使用网络库,啊哈。

按位分割整数的例子如下

buffer[0] = integer&0xFF;
buffer[1] = (integer>>8)&0xFF;
buffer[2] = (integer>>16)&0xFF;
buffer[3] = (integer>>24)&0xFF;

在典型的消息传递协议中,最直接的方法是拥有一组可以轻松转换的消息,使用继承(或组合)以及字节对齐结构(在这种情况下对于从原始数据指针进行转换很重要)可以使这相对容易:

struct Header
{
    unsigned char message_type_;
    unsigned long message_length_;
};
struct HeartBeat : public Header
{
    // no data, just a heartbeat
};
struct PlayerData : public Header
{
    unsigned long position_x_;
    unsigned long position_y_;
};
unsigned char* raw_message; // filled elsewhere
// reinterpret_cast is usually best avoided, however in this particular
// case we are casting two completely unrelated types and is therefore
// necessary
Header* h = reinterpret_cast<Header*>(raw_message);
switch(h)
{
    case HeartBeat_MessageType:
    break;
    case PlayerData_MessageType:
    {
        PlayerData* data = reinterpret_cast<PlayerData*>(h);
    }
    break;
}

我在Skype上与我认识的一个程序员交谈,他向我展示了我正在寻找的解决方案。

playerPosition.X = *(int*)(bufferIncoming+3);

我不记得怎么让它工作,或者它叫什么。但现在看来一切都好了。

谢谢大家的帮助:)