我正在使用以下代码测试struct的浅层副本:
#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;
}
我预计结果应为:
back
back
但它是:
back
go
修改:我预计会因为浅版,str_1.name
和str_2.name
应始终指向相同位置。
编辑:通过动态分配,我得到了我的预期:
#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;
}
结果是:
back
back
我在这里误解了什么?
答案 0 :(得分:2)
str_2 = str_1;
采取浅层副本。
但并不意味着对name
中str_1
所指向的任何后续更改都将自动反映在str_2
中。< / p>
(实际上,您应该使用const char*
作为字符串类型,因为您要分配只读字符串文字)。
答案 1 :(得分:2)
拿一张纸慢慢地画出你认为在每一步发生的事情,这应该变得清晰。
让我们画出struct str
:
---------------------
| const char * name |
---------------------
| int value |
---------------------
让我们在地址0xabcdef10
表示一个字符串,如下所示:
--0xabcdef10---------------------
| "string\0" |
---------------------------------
因此,当我们初始化str_1
时,我们需要一些内存位置来保持&#34; go&#34;,让我们调用0xaaaaaa00
--0xaaaaaa00---------------------
| "go\0" |
---------------------------------
然后我们用指向它的指针初始化str_1
:
struct str str_1 = {"go", 255};
--str_1---------------------------
| const char * name = 0xaaaaaa00 |
----------------------------------
| int value = 255 |
----------------------------------
现在我们采用str_1
的浅表副本,并将其称为str_2
:
--str_2---------------------------
| const char * name = 0xaaaaaa00 |
----------------------------------
| int value = 255 |
----------------------------------
接下来我们执行str_1.name = "back";
。和以前一样,我们首先要创建新字符串。让我们把它放在0xbbbbbb00
:
--0xbbbbbb00---------------------
| "back\0" |
---------------------------------
然后我们将其分配给str_1.name
,所以str_1
现在看起来像:
--str_1---------------------------
| const char * name = 0xbbbbbb00 |
----------------------------------
| int value = 255 |
----------------------------------
请注意,我们尚未更改str_2
。
因此,当我们查看我们的最终&#34;记忆&#34;时,我们会看到:
--0xaaaaaa00---------------------
| "go\0" |
---------------------------------
....
--0xbbbbbb00---------------------
| "back\0" |
---------------------------------
....
--str_1---------------------------
| const char * name = 0xbbbbbb00 |
----------------------------------
| int value = 255 |
--str_2---------------------------
| const char * name = 0xaaaaaa00 |
----------------------------------
| int value = 255 |
----------------------------------
所以str_1指向新字符串,str_2指向旧字符串。
如果你描述为动态,你永远不会更新结构中的指针,你可以通过相同的练习来描绘在这种情况下内存会发生什么。
答案 2 :(得分:1)
str_2 = str_1;
制作了结构本身的硬拷贝。例如,value
成员对于每个结构都是唯一的。
但是你得到了任何指针成员的软拷贝,因为拷贝不会影响任何指针的指向数据。这意味着在复制之后,name
和str_1
的{{1}}指针指向文字str_2
。
然后"go"
仅在str_1.name = "back";
指向的地方发生变化。它不会改变str_1.name
指向的地方。
当您使用malloc和strcpy时,您可以更改指向的数据并获取所有内容的完整硬拷贝。