编辑存储在字节数组中的数据

时间:2014-10-01 19:39:24

标签: c++ arrays byte

我一直在努力将经常运行的数据存储到大量的unsigned char中(因为C ++没有字节类型)。因此,如果我将一个浮点存储到char数组中,它将占用4个无符号字符。很简单,除非现在如果我想在数组中编辑那些数据,我需要同时访问所有4个元素,据我所知这是不可能的。 那么,有没有办法将4个无符号字符编辑成我想要的浮点值而不需要求助于memcpy()?

示例:

#include <iostream>
#include <string.h>
#include <stdint.h>

using namespace std;

struct testEntity {

    float density;
    uint16_t xLoc, yLoc;
    uint16_t xVel, yVel;
    uint16_t xForce, yForce;
    uint16_t mass;
    uint8_t UId;
    uint8_t damage; 
    uint8_t damageMultiplier;
    uint8_t health;
    uint8_t damageTaken;
};


int main()
{

    testEntity goblin { 1.0, 4, 5, 5, 0, 0, 0, 10, 1, 2, 1, 10, 0 };
    testEntity goblin2;
    unsigned char datastream[24];
    unsigned char* dataPointer = datastream;

    memcpy(&datastream, &goblin, sizeof(testEntity));


    //I know that datastream[0..3] contains information on goblin.density
    //How would I edit goblin.density without memcpy into another testEntity structure?

    memcpy(&goblin2, &datastream, sizeof(testEntity));

return 0;
}

3 个答案:

答案 0 :(得分:1)

这就是我的所作所为:

#include <iostream>
#include <string.h>
#include <stdint.h>

using namespace std;

struct testEntity {

    float density;
    uint16_t xLoc, yLoc;
    uint16_t xVel, yVel;
    uint16_t xForce, yForce;
    uint16_t mass;
    uint8_t UId;
    uint8_t damage; 
    uint8_t damageMultiplier;
    uint8_t health;
    uint8_t damageTaken;
};


int main()
{

    testEntity goblin = { 1.0, 4, 5, 5, 0, 0, 0, 10, 1, 2, 1, 10, 0 };
    testEntity goblin2;
    unsigned char datastream[24];
    unsigned char* dataPointer = datastream;
    testEntity *goblinP;

    memcpy(datastream, &goblin, sizeof(testEntity));


    goblinP = (testEntity *) datastream;

    cout << goblinP->density << endl;

return 0;
}

答案 1 :(得分:0)

通过使用联合,您可以通过各种方式访问​​内存位置,也许这​​就是您正在寻找的内容(如果我理解正确的话):

typedef union 
{
  struct testEntity 
  {
    float density;
    uint16_t xLoc, yLoc;
    uint16_t xVel, yVel;
    uint16_t xForce, yForce;
    uint16_t mass;
    uint8_t UId;
    uint8_t damage; 
    uint8_t damageMultiplier;
    uint8_t health;
    uint8_t damageTaken;
  } te;
  char datastream[24];
} myunion;


...
myunion goblin = { 1.0, 4, 5, 5, 0, 0, 0, 10, 1, 2, 1, 10, 0 }; 

char* goblinP = goblin.datastream;

or e.g. goblin.te.health

修改

最好为结构创建一个序列化/反序列化函数,以便将它从/转换为结构。

e.g。

ostream& operator<<(ostream& o, const testEntity &in)
{
  typedef union { float f; char bytes[4]; } floatunion;
  floatunion fu = in.density;
  o.write( fu.bytes, 4 );
  ...
  return o;  
}

答案 2 :(得分:0)

您的计划:

goblinP = (testEntity *)datastream;

违反了严格的别名规则。换句话说,规则是只能通过具有该对象类型的表达式来访问对象;除了少数例外。您可以将对象作为无符号字符访问,但不能将无符号字符作为对象访问。

这段代码可能似乎可以正常工作,但你真的玩火,因为编译器可能决定优化你读取对象的尝试,因为标准说你有效地读取未初始化的变量

要做你想做的事,请声明你的缓冲行:

testEntity goblin;

然后您可以通过执行以下操作将其别名为字节:

unsigned char *datastream = reinterpret_cast<unsigned char *>(&goblin);

您可以通过datastream写入字节,然后访问goblin以查看您的内容。 (当然,这仍然取决于你实际上是testEntity的有效对象表示所写的字节。)