Continuing some thoughts from here and here, I want to memcpy some data into my array.
With the above s_object, I have one char pointer to dynamically-allocated space for the name of the object. Then I have an array of (is it stack-allocated?) chars for the object's description.
I just want to make sure I correctly understand memcpy before I totally blow something up.
Let's say I have this:
EDIT: Fixed the sizeof() to return the size of the struct instead of the parameter (possibly a pointer).
What I expect to happen is:
x, y, vel_x, vel_y, accel_x, accel_y will all be copied as expected.
The pointer to name will be copied (they both point to the same location), but I would want to allocate the array myself and then manually copy character-by-character the string over.
The description will
Technically, description is just a pointer, like name is. But since it's allocated on the stack (is this correct?), it wouldn't be pointing to the same stack address as the original would it? As soon as the other stack object goes out of scope, both the current and the original s_object objects will be invalid (at least, the description part of it).
Or does memcpy copy all 32 bytes? I don't know if I want to do this:
or just
I had the impression that structs are assignable in C:
which_array->array[which_array->size] = which_object;
Do what it takes with the name pointer. The contents of the automatic array (description) should be automatically copied with the assignment (or with the memcpy).
I had the impression that structs are assignable in C:
Well, that's true. However:
The temp object is destroyed when some_example() goes out of scope. Simply assigning the which_object pointer to the which_array->array array won't do it.
The contents of the automatic array (description) should be automatically copied with the assignment (or with the memcpy).
Should be or will be? Do I have to worry about different platforms OR compilers (gcc/g++/MSVC/Borland C)?
This assignment does a shallow memberwise copy. It is basically human-readable and more error-proof way of calling memcpy on a single object.
Should be or will be? Do I have to worry about different platforms OR compilers (gcc/g++/MSVC/Borland C)?
I would venture to say, will be (either way). I don't see what makes you even doubt: the array is part of the struct. When bytes get copied, the values of the bytes making up the char array are copied with them.
[Edit]
Wait, you are only copying sizeof(s_object*) worth of bytes?!
void add_object_item(s_object_array *which_array, s_object *which_object) { ... // ensuring enough room to add it to the array memcpy(&which_array->array[which_array->size], which_object, sizeof(which_object)); which_array->size++; }
That won't copy the whole struct. First-hand example of assigning being less error-prone.
I had mistyped the code in the OP. It's fixed.
I want to copy all 60 bytes of the s_object object from the which_object parameter into a new entry contained on the which_array array.
Instead of which_array->array containing pointers to newly-malloced instances, I wanted to allocate the room on the array itself so I could just step through them individually.
Since both name and description are char arrays, I was wondering whether memcpy would copy description in the same way that it copies name: ie, a shallow copy to the pointer only, and not a deep copy of the actual text.
Since name is allocated on the heap, while description is allocated on the stack, I didn't know whether it would shallow-copy the pointer, or whether the description gets deep-copied.
Wait, you are only copying sizeof(s_object*) worth of bytes?!
That was a typo on my part. It was supposed to be a sizeof(s_object), not sizeof(s_object*).
Since name is allocated on the heap, while description is allocated on the stack, I didn't know whether it would shallow-copy the pointer, or whether the description gets deep-copied.
There should be no room for confusion. It copies the content of the struct. If the struct contains a fixed-size array, it copies the array (because it's part of the struct). If it contains a pointer, it copies the pointer. It will not duplicate whatever the pointer is pointing to, because that is not part of the struct (it would basically have to create a new pointer to a memory region that holds the copy, but then it wouldn't be copying the pointer).
Does that answer your question?
Essentially. I had to write up a test program to make sure I was doing it correctly.
That's what I suspected all along, but didn't really want to write up 100+ lines of test code just to make sure that I was right. Oh well, it's another program to stick under my "~/programming/temp/things_i_learned/" pile
.../temp/things_i_learned/...
Is that not irony?
Not if I have a really bad short-term memory
There should be no room for confusion. It copies the content of the struct. If the struct contains a fixed-size array, it copies the array (because it's part of the struct). If it contains a pointer, it copies the pointer. It will not duplicate whatever the pointer is pointing to, because that is not part of the struct (it would basically have to create a new pointer to a memory region that holds the copy, but then it wouldn't be copying the pointer).
Which is exactly why C++ provides copy constructors.
In C, I'd write up a clone_XXX() function for the struct in question, for any struct that requires deep copying.
Tobias, this is a clone_XXX() function. So within said function, I was trying to determine which of the two pointers/arrays were going to be deep copied, and which were going to be short.
My answer:
typedef struct { int x, y; float vel_x, vel_y; float accel_x, accel_y; char *name; // Shallow copy (pointer only) char description[32]; // Deep copy (all 32 bytes) } s_object;
I'm so used to C++ that the usage of memcpy() is rather new to me
The array is in the same contiguous block of memory and is also shallow copied. If you have an array of pointers only the pointer addresses would be copied.
Peter: When you say "the array"... are you talking about char *name; or char description[32]; ?
Only one of them is an array
I was trying to determine which of the two pointers/arrays were going to be deep copied, and which were going to be short.
I don't quite understand the distinction you make between "deep" and "short" copying here - and I'm not talking about what those terms mean. I just find it confusing to use those terms when talking about what happens when you copy a struct.
Again, that's because what happens is really simple: the content of the struct is copied because you copy the raw bytes that make up the struct. If you have an array in the struct, then the array gets copied. If you have a pointer, the pointer gets copied. Nothing else is touched.
Think of it this way: to memcpy() the struct is just a raw block of data. To decide whether it should duplicate a pointer or not it would need to interpret some of this data. Since it doesn't know anything about your struct, it doesn't know how to do that. So it doesn't.
In C, this structure...
typedef struct { int x; float y; char *name; char description[32]; } demo_struct;
... would look like this in memory (32-bit code).
Byte | Description 00 01 02 03 = int 04 05 06 07 = float 08 09 0a 0b = 32-bit pointer to some memory 0c 0d 0e 0f 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 20 21 22 23 24 25 26 27 28 29 2a 2b = 32 chars of description[32]
Since memcpy only copies a string of bytes it copies the pointer and not what the pointer points to... C is just too stupid to know what your pointing it at. To make a unique copy of that string you could always use strdup like this...
And that's it...
Hell, that was kind of hard...