struct Data {
double latitude; // 8
float speed ; // 4
unsignedshort id ; // 2
bool status ; // 1
//char pad ; // 1
} data; // byte count: 16
int sz = sizeof(data);// perfect 16
// initialize as:
data.latitude = sqrt(2.);
data.speed = 12.34f;
data.id = 35;
data.status = true;
char *source = (char *)(&data);
char *target = newchar [sz];
// Try to copy to target
memcmp(target, source, sz); // not copy any! Why?
int sz1 = sizeof(*target); // = 1 ?
// Try to copy to a Data struct
Data t1;
memcmp(&t1, source, sz); // not copy any! Why?
char *p = (char *)(&t1);
for (int i = 0; i < sz; ++ i) {
p[i] = source[i];
}
// now all fields are copied. They are right.
bool ok = ((t1.latitude == data.latitude) &&
(t1.speed == data.speed ) &&
(t1.id == data.id ) &&
(t1.status == data.status ));
// true
Why memcpy() does not copy any, while documentation says "The function does not check for any terminating null character in source - it always copies exactly num bytes." ?
You're going kick yourself ... you're using memcmp when you mean to use memcpy!
However, sizeof(*target) will always be 1 since target points to a char and a char is size 1 by definition. sizeof can't tell how many characters a char pointer "actually" points to.
1. The padding is up to the implementation. If you add two more char in there, the size could be 24 for example. The total size is >= size of the parts.
2. You typo'd. You wrote memcmp (memory compare) instead of memcpy (memory copy).
I, too, didn't realize you were using memcmp instead of memcpy until tpb said it.
That being said, considering this is C++, this is needlessly messy code. Why are you using C++ as if it were some restricted form of C? If I understand your code correctly, it can be simplified as:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
#include <cmath>
int main()
{
struct Data {
double latitude; // 8
float speed ; // 4
unsignedshort id ; // 2
bool status ; // 1
};
Data data = { sqrt(2.0), 12.34f, 35, true };
Data t1 = data;
// guaranteed to be OK now
}
@icy1
Wait, why are you wrapping the call to memcpy in an exception? I have never heard of a C function throwing a C++ exception, please explain.
I, too, didn't realize you were using memcmp instead of memcpy until tpb said it.
I didn't see it at first, either. I copied the code and added the minimum to get it to compile and the compiler warned of a "statement with no effect". That's when I saw it. Yet another point for maximizing your compiler warning levels!
@Ganado erm, yeah, you can ignore that... wasn't really thinking there, lol. Absolutely right; C functions shouldnt throw C++ exceptions. std::copy could throw, right? Perhaps I was thinking that.
Edit: You know what I think it was -- I saw the comment "Try to copy to target" and I must've already begun to translate it into code. As you can see, I don't call many C functions =S
Edit2: Actually, can't you just write Data target = data; and be done with it? As long as your struct doesn't contain pointers, a shallow copy should be fine. If it does, you'll just take a few lines to perform the copy with the pointer and its size, etc.
std::copy could throw, right? Perhaps I was thinking that.
Yep, that can throw if an overloaded assignment operator or iterator throws.
can't you just write Data target = data;
Exactly, I agree. I don't understand why the OP made this so horribly complicated. And if the struct contained pointers in it, memcpy would only do shallow copies either way.