开发者

Trouble with template method which reads type from a byte array

I have a class that represents some file data. The file contains some headers.

Within the class definition I also have a template method that looks like this

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

So for example, if I want to read a particular field of the header I can simply call the get method.

i.e. uint64 GetCRC64() { return Get(1); }

However, the trouble I'm having is that it doesn't appear to be wr开发者_Go百科iting the data as expected.

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

As I write _data to a file. Using a hex editor the file seems to be wrong.

Now, before you ask yes I am aware that it's sensitive to endianess. However this code will only ever be run on the intel platform. So always little endian.

The header looks like this: 1byte - version 8 byte - crc64 8 byte - serial number

So if I had a version number 1 and a crc = 0x001122334455667788 and serial number 1 I would expect it to look like this in the written file.

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

But instead I see something like:

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

Again this is from memory but it seems to be writing the data at the wrong offset. I'll be able update this post with the exact data being written and read and the hex output in a few hours.

The offsets I am using for Set are 0 (version), 1 (crc) & 9(serial #). I think it's to do with Get/Set. But I don't quite see why. Maybe someone can spot why it isn't working quite as expected.

I think this example illustrates the problem I'm having better. Any idea why it doesn't print out the value fed in by hand?

#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));
}


Your casts are wrong. You can only do arithmetic on pointers to complete types. Try it like this:

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

Speaking of, why not implement a single val() accessor for both reading and writing?

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

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜