Reputation: 91
This is my first question.
I am learning C. And I heard about shallow copy. As I understood, shallow copy means that you copy the address of the object instead of its value. This means that every change to the copied object will affect the original object.
#include<stdio.h>
struct Person {
char *name;
int age;
};
int main (void)
{
struct Person p1 = {"jon", 20};
struct Person p2 = p1;
p2.name = "mark";
p2.age = 26;
printf ("%s\n", p1.name); // print 'jon' not 'mark'!
printf ("%d\n", p1.age); // prinf 20 not 26
return 0;
}
I tried the above code, and I expeted that the modification of 'p2' will affect 'p1'. But the the content of 'p1' remains the same as if I implemented a deep copy.
Upvotes: 2
Views: 179
Reputation: 181008
I tried the above code, and I expeted that the modification of 'p2' will affect 'p1'. But the the content of 'p1' remains the same as if I implemented a deep copy.
You have indeed performed a shallow copy of p1
onto p2
, but that's not what you think it is. Your p1
and p2
are distinct objects with independent members, but pointer members p1.name
and p2.name
(presently) have the same pointer value, and as long as that is true, if the string to which they both point were modified, then you could observe it through both p1
and p2
:
int main(void) {
struct Person p1 = {(char[]) {"jon"}, 20};
struct Person p2 = p1;
// Confirm copying
printf ("%s\n", p2.name); // prints 'jon'
// Confirm shallowness
p2.name[0] = 'R';
printf ("%s\n", p1.name); // prints 'Ron'
printf ("%s\n", p2.name); // prints 'Ron'
return 0;
}
For a deep copy, on the other hand, you would need to make an independent copy of that string for p2.name
to point to. Then no modification you can make to one object will be visible via the other. Example:
int main(void) {
struct Person p1 = {(char[]) {"jon"}, 20};
struct Person p2 = p1;
// complete the deep copying:
p2.name = strdup(p2.name);
// Confirm copying
printf ("%s\n", p2.name); // prints 'jon'
// Confirm deepness
p2.name[0] = 'R';
printf ("%s\n", p1.name); // prints 'jon'
printf ("%s\n", p2.name); // prints 'Ron'
return 0;
}
And in this case, that's as deep as you can go, because the objects to which p1.name
and p2.name
point do not contain any pointers themselves. There is a distinction between shallow and deep copying only for objects that contain pointers.
It is also possible to take the address of an object, and then modify the object indirectly through that address (a pointer), but that's not any form of copying. Creating a copy implies producing a distinct object, not a mere alias for the original.
Upvotes: 3
Reputation: 8354
Here is a real "shallow copy". This example exhibits the consequences you were expecting.
#include <stdio.h>
struct Person {
char *name;
int age;
};
int main( void )
{
char boy[ 16 ] = "jon"; // must be a "mutable" buffer!
struct Person p1 = { boy, 20 };
struct Person p2 = p1;
printf( "{ %s %d } { %s %d }\n", p1.name, p1.age, p2.name, p2.age );
strcpy( p2.name, "mark" ); // Where is p2.name pointing??
p2.age = 26; // change value
printf( "{ %s %d } { %s %d }\n", p1.name, p1.age, p2.name, p2.age );
return 0;
}
{ jon 20 } { jon 20 }
{ mark 20 } { mark 26 }
It's ALWAYS a good idea to add enough debugging print statements to your code to shine light into the black box. Better is to use a debugger to watch the flow of execution and monitor variables' values.
Upvotes: 1
Reputation: 1629
The way you've written it now makes p2
a copy of p1
. You want to create a pointer to the address of p1
to modify it.
#include <stdio.h>
struct Person {
char *name;
int age;
};
int main(void)
{
struct Person p1 = {"jon", 20};
struct Person *p2 = &p1;
p2->name = "mark";
p2->age = 26;
printf ("%s\n", p1.name);
printf ("%d\n", p1.age);
return 0;
Output:
mark
26
You can use p2->member
or (*p2).member
to access member variables, since p2
is a pointer and needs to be dereferenced before you can access them.
Upvotes: 0