1

Say i have a struct like

typedef struct {
    unsigned char flag, type;
    unsigned short id;
    uint32 size;
} THdr;

and a buffer of data coming from a UDP comunication, i have a buffer of bytes and its size (data and data_size). data size is bigger than sizeof(THdr).

The struct is at the beginning of the buffer, and i want to copy it to a struct defined in the code, THdr Struct_copy .

I know that i can use memcpy(&Struct_copy,data[0],sizeof(Struct_copy)); but i would like to use a "C++ style" way, like using std::copy.

any clue?

MikO
  • 18,243
  • 12
  • 77
  • 109
BiA
  • 364
  • 2
  • 6
  • 23
  • If you have a working single-line implementation, why complicate it (and quite possibly slow down) because you want something more 'stylish'? `memcpy` is a fine solution for this, that's what it's for. – Niels Keurentjes May 10 '13 at 13:44
  • 1
    Use `std::memcpy` instead :-) `std::` makes it more C++ish! – masoud May 10 '13 at 13:47
  • because depending on the compiler memcpy can be slower than std::copy, at least is what they said in http://stackoverflow.com/questions/4707012/c-memcpy-vs-stdcopy – BiA May 10 '13 at 13:49
  • That `uint32` -- if coming over the network, it should have a different byte ordering. – Yakk - Adam Nevraumont May 10 '13 at 13:58
  • `memcpy` is not correct here either, and in general you can't do stuff like that portably (not saying it won't work in all cases you care for). For example, in general the compiler can inject padding between struct members to ensure proper alignment. In order to get safe offsets, you would have to enable packing in the structure which is not possible portably. `char` and `short` may not have the sizes you desire. `uint32` may not even be available on the platform. All of them can have wrong endianness… Yes, C++ is fun! ;-) – Michał Górny Dec 17 '15 at 16:58

2 Answers2

2

There is no "clever" way to do this in C++. If it doesn't involve memcpy, then you need std::copy and you will have to use casts to const unsigned char * to make the datatype of the source and/or destination match up.

There are various other ways to "copy some data", such as type-punning, but again, it's not a "better" solution than memcpy - just different.

C++ was designed to accept C-code, so if there's nothing wrong with your current code, then I don't see why you should change it.

Mats Petersson
  • 126,704
  • 14
  • 140
  • 227
1

How about something like

THdr hdr;
std::copy(&hdr, &hdr + 1, reinterpret_cast<THdr*>(data));

Should copy one THdr structure from data to hdr.

It can also be much simpler:

THdr hdr;
hdr = *reinterpret_cast<THdr*>(data);

This last works in C as well:

THdr hdr;
hdr = *(THdr *) data;

Or why not create a constructor that takes the data as input? Like

struct THdr
{
    explicit THdr(const unsigned char* data)
        {
            THdr* other = reinterpret_cast<THdr*>(data);
            *this = *other;
        }

    // ...
};

Then it can be used such as

THdr hdr(data);
Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
  • Doesn't `reinterpret_cast` have run-time efficiency penalty? – masoud May 10 '13 at 13:50
  • @MM. Nope, it just tells the compiler to treat one type as another type, i.e. it should "reinterpret" the type. – Some programmer dude May 10 '13 at 13:52
  • Maybe that "reinterpret" imposes cost... Does it cost compile-time or run-time? I'm a litte confused! – masoud May 10 '13 at 13:57
  • @MM. Definitely no runtime-cost, barely even compile-time cost. Whatever "cost" it has on the compilation, it will be negligible and not even measurable. It's actually only a nicer way of the old C-style cast. – Some programmer dude May 10 '13 at 13:59
  • tryed, but the compiler says [bcc32 Error] def.h(104): E2031 Cannot cast from 'const unsigned char *' to 'THdr *' – BiA May 10 '13 at 14:22
  • maybe it should not be const unsigned char* but only unsigned char* – BiA May 10 '13 at 14:28
  • No "Should copy one THdr structure from data to hdr": from hdr to data – Mert Mertce Jun 10 '15 at 10:19
  • 1
    `reinterpret_cast` is wrong here. You mustn't dereference a `reinterpret_cast` pointer unless you `reinterpret_cast` it back to the original type, see [When to use reinterpret_cast?](http://stackoverflow.com/questions/573294/when-to-use-reinterpret-cast). You want to use double `static_cast` instead (to `void*`, then to target type). – Michał Górny Dec 17 '15 at 16:19