Reputation: 6121
I'm testing shallow copy for struct with this code:
#include "stdio.h"
#include "conio.h"
int main() {
struct str {
char * name;
int value;
};
struct str str_1 = {"go", 255};
struct str str_2;
str_2 = str_1;
str_1.name = "back";
printf("%s\n",str_1.name);
printf("%s\n",str_2.name);
printf("\n");
system("pause");
return 0;
}
I expected the result should be:
back
back
But it was:
back
go
Edit: I expected that because with shallow copy, str_1.name
and str_2.name
should always point to same place.
Edit: And with dynamic allocation, I got what I expected:
#include <stdio.h>
#include <conio.h>
#include <string.h>
int main() {
struct str {
char * name;
int value;
};
struct str str_1;
struct str str_2;
str_1.name = (char*) malloc(5);
strcpy(str_1.name,"go");
str_2 = str_1;
strcpy(str_1.name,"back");
printf("%s\n",str_1.name);
printf("%s\n",str_2.name);
printf("\n");
system("pause");
return 0;
}
The result is:
back
back
What was I misunderstand here ?
Upvotes: 2
Views: 148
Reputation: 2491
Take a piece of paper and draw what you think is happening at each step slowly, and this should become clear.
Let's draw struct str
as so:
---------------------
| const char * name |
---------------------
| int value |
---------------------
And let's denote a string at address 0xabcdef10
as so:
--0xabcdef10---------------------
| "string\0" |
---------------------------------
So, when we initialise str_1
, we need some memory location which will hold "go", lets call that 0xaaaaaa00
--0xaaaaaa00---------------------
| "go\0" |
---------------------------------
Then we initialise str_1
with a pointer to that:
struct str str_1 = {"go", 255};
--str_1---------------------------
| const char * name = 0xaaaaaa00 |
----------------------------------
| int value = 255 |
----------------------------------
Now we take a shallow copy of str_1
, and call it str_2
:
--str_2---------------------------
| const char * name = 0xaaaaaa00 |
----------------------------------
| int value = 255 |
----------------------------------
Next we execute str_1.name = "back";
. As before, we first want to create the new string. Lets put that at 0xbbbbbb00
:
--0xbbbbbb00---------------------
| "back\0" |
---------------------------------
Then we assign it to str_1.name
, so str_1
now looks like:
--str_1---------------------------
| const char * name = 0xbbbbbb00 |
----------------------------------
| int value = 255 |
----------------------------------
Note that we haven't changed str_2
.
So, when we look at our final "memory", we see:
--0xaaaaaa00---------------------
| "go\0" |
---------------------------------
....
--0xbbbbbb00---------------------
| "back\0" |
---------------------------------
....
--str_1---------------------------
| const char * name = 0xbbbbbb00 |
----------------------------------
| int value = 255 |
--str_2---------------------------
| const char * name = 0xaaaaaa00 |
----------------------------------
| int value = 255 |
----------------------------------
So str_1 points at the new string, and str_2 points at the old string.
In case you describe as dynamic, you never update the pointers in the struct, you could go through the same exercise to draw out what happens to memory in that case.
Upvotes: 2
Reputation: 214395
str_2 = str_1;
makes a hard copy of the struct itself. For example the value
member will be unique for every struct.
But you got a soft copy of any pointer members, since the copy does not affect the pointed-at data of any pointer. Meaning that after the copy, the name
pointer of both str_1
and str_2
points at the literal "go"
.
And then str_1.name = "back";
only changes where str_1.name
points at. It doesn't change where str_2.name
points at.
When you used malloc and strcpy, you change the pointed-at data and get a complete hard copy of everything.
Upvotes: 1
Reputation: 234785
str_2 = str_1;
did take a shallow copy.
But that doesn't mean that that any subsequent alteration to what name
points to in str_1
will be automatically reflected in str_2
.
(Really you should use const char*
as the string type as you are assigning read-only string literals).
Upvotes: 2