Why memcpy() does not copy any?

The following struct has 16 bytes.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
    struct Data {
        double           latitude; // 8
        float            speed   ; // 4
        unsigned short   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 = new char [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." ?
Last edited on
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.
Last edited on
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).

works as intended
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
#include <cmath>
#include <cstring>
#include <iostream>
#include <string>

using namespace std;

struct Data {
    double           latitude; // 8
    float            speed   ; // 4
    unsigned short   id      ; // 2
    bool             status  ; // 1
};           // byte count: 16    

void Show(const Data& d, const string& name)
{
    cout << boolalpha;
    cout << name <<" ("<<sizeof(d)<<" bytes):\n";
    cout << "  "<< d.latitude << endl <<
            "  "<< d.speed << endl <<
            "  "<< d.id << endl <<
            "  "<< d.status << endl << endl;
}

int main() 
{
    Data data;
    size_t sz = sizeof(data);

    data.latitude = sqrt(2.);
    data.speed    = 12.34f;
    data.id       = 35;
    data.status   = true;
    Show(data, "data");

    Data target;
    memcpy(&target, &data, sz);
    Show(target, "target");

// Edit: brain fart -- C functions dont throw C++ exceptions!  ;D
/*
    // Try to copy to target 
    try
    {
        memcpy(&target, &data, sz);
        Show(target, "target");     
    }
    catch(...)
    {
        cout << "Error during copy!!!\n";
        return -2;
    }
*/

    return 0;
}


data (16 bytes):
  1.41421
  12.34
  35
  true

target (16 bytes):
  1.41421
  12.34
  35
  true
Last edited on
oooooooooooops! it should be 'memcpy'.
You are right that sizeof(*target) should be 1. Thank you. Solved!
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
        unsigned short   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.
Last edited on
Ganado wrote:
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!
Last edited on
@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.
Last edited on
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.
Topic archived. No new replies allowed.