模板方法的麻烦,从字节数组中读取类型

时间:2011-07-26 00:22:03

标签: c++

我有一个代表一些文件数据的类。该文件包含一些标题。

在类定义中,我还有一个看起来像这样的模板方法

template< typename T>
T Get(int offset)
{
  return *((T*)(_data + offset));  // where _data is a member variable. unsigned char*
}

例如,如果我想读取标题的特定字段,我可以简单地调用get方法。

即。     uint64 GetCRC64()     {       return Get(1);     }

然而,我遇到的麻烦是它似乎没有按预期写入数据。

template <typename T>
void Set(int offset, T value)
{
  *((T*)(_data + offset)) = value;  // where _data is a member variable. void*
}

当我将_data写入文件时。使用十六进制编辑器,文件似乎是错误的。

现在,在你提出肯定之前我知道它对于endianess非常敏感。但是,此代码只能在intel平台上运行。所以总是小端。

标题如下所示: 1byte - 版本 8字节 - crc64 8字节 - 序列号

因此,如果我的版本号为1且crc = 0x001122334455667788且序列号为1,我希望它在书面文件中看起来像这样。

  

01 00 11 22 33 44 55 66 77 88 00 00 00 00 00 00 00 01

但相反,我看到的是:

  

01 00 00 00 00 00 00 00 00 00 11 22 33 44 55 66 77 88

这又是来自内存,但它似乎是在错误的偏移处写入数据。 我将能够用几小时内写入和读取的确切数据和十六进制输出更新这篇文章。

我用于Set的偏移量为0(版本),1(crc)&amp; 9(序列号)。我认为这与Get / Set有关。但我不太明白为什么。也许有人可以发现为什么它没有按预期工作。

我认为这个例子说明了我有更好的问题。知道为什么它没有打印出手工输入的价值吗?

#include <stdio.h>
#include <stdlib.h>

struct Test
{
    Test()
    {
        _data = new unsigned char[100];
        // Fill _data with known data

        // first byte is 1
        _data[0] = 1;

        // Next 8 bytes are 0x0102030405060708
        _data[1] = 0x01;
        _data[2] = 0x02;
        _data[3] = 0x03;
        _data[4] = 0x04;
        _data[5] = 0x05;
        _data[6] = 0x06;
        _data[7] = 0x07;
        _data[8] = 0x08;

        _data[9] = 0x0A;
        _data[10] = 0x0B;
        _data[11] = 0x0C;
        _data[12] = 0x0D;
        _data[13] = 0x0E;
        _data[14] = 0x0F;
        _data[15] = 0x0A;
        _data[16] = 0x0B;
    }

    template <typename T> T & val(size_t offset) { return *(reinterpret_cast<T*>(_data) + offset); }
    template <typename T> const T & val(size_t offset) const { return *(reinterpret_cast<T*>(_data) + offset); }


    unsigned char* _data;
};


int main(int argc, char* argv[])
{
    Test t;

    printf("t(0)=0x%X\n", t.val<char>(0));
    printf("t(1)=0x%llX\n", t.val<unsigned long long>(1));
    printf("t(9)=0x%llX\n", t.val<unsigned long long>(9));
}

1 个答案:

答案 0 :(得分:2)

你的演员阵容错了。你只能对指针进行算术来完成类型。试试这样:

T * const p = reinterpret_cast<T*>(_data);
return *(p + offset);
// or
*(p + offset) = value;

说到为什么不为阅读和写作实现一​​个val()访问器?

T & val(size_t offset) { return *(reinterpret_cast<T*>(_data) + offset); }
const T & val(size_t offset) const { return *(reinterpret_cast<T*>(_data) + offset); }