C/C++结构体中的深copy和浅copy&&结构体偏移量的两种求法

浅copy:

编译器仅仅拷贝了结构体的值,而没有创建新的内存空间,而是共享同一块内存空间。当结构体成员中含有Buf的时候,拷贝之后释放内存就不会出现问题。但是如果结构体中含有指针变量的时候,编译器只会copy指针变量,而对应的内存空间却不会缺不再多分配。

代码:

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
#define _CRT_SECUFE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
typedef struct note {
char a[64];
int b;
char*c;
}note;
void my_copy(note*from, note*to) {
*to = *from;
//memcpy(to,from,sizeof(note));//和上述操作等效
}
int main() {
note d, e;
strcpy(d.a, "123");
d.b = 456;
while ((d.c = (char*)malloc(64 * sizeof(char))) == NULL)
exit(1);
strcpy(d.c, "789");
printf("d的值为:\n");
printf("%s\n%d\n%s\n", d.a, d.b, d.c);
my_copy(&d, &e);
printf("e的值为:\n");
printf("%s\n%d\n%s\n", e.a, e.b, e.c);
if (d.c != NULL) {
free(d.c);
d.c = NULL;
}
if (e.c != NULL) {
free(e.c);
e.c = NULL;
}
return 0;
}

以此样例为例,输出结果为:

1
2
3
4
5
6
7
8
d的值为:
123
456
789
e的值为:
123
456
789

然后接着某些编译器如vs的编译器就会报错。出错位置为

1
2
3
4
if (e.c != NULL) {
free(e.c);
e.c = NULL;
}

这是由于将结构体d内存元素直接赋给结构体e时,即进行 e= d操作时,由于结构体中含有指针元素,d结构体中的指针已经动态分配内存,而操作完成之后e中指针的值也会写上d动态分配内存的地址,因此d和e指向同一内存空间。这样当d中指针d.c释放内存之后,由于e.c仍然指向该部分内存,而不指向空,此时会强制释放掉e.c所指向内存,由于此处内存已经释放过了,处于不能被访问状态,而e.c又强制释放该内存,就会造成vs编译器报错。这就是前copy的弊端。

深copy:

编译器会为拷贝的对象分配一定的内存空间。

以上述代码为例,只需在进行 e= d操作之后再为e.c重新分配内存,然后执行strcpy(e,d)即可。这样e.c和d.c分别指向两块不同的内存,这样就不会出现上面那种错误。

代码:

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
#define _CRT_SECUFE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
typedef struct note {
char a[64];
int b;
char*c;
}note;
void my_copy(note*from, note*to) {
*to = *from;
//memcpy(to,from,sizeof(note));//和上述操作等效
while ((to->c = (char*)malloc(64 * sizeof(char))) == NULL)
exit(1);
strcpy(to->c, from->c);
}
int main() {
note d, e;
strcpy(d.a, "123");
d.b = 456;
while ((d.c = (char*)malloc(64 * sizeof(char))) == NULL)
exit(1);
strcpy(d.c, "789");
printf("d的值为:\n");
printf("%s\n%d\n%s\n", d.a, d.b, d.c);
my_copy(&d, &e);
printf("e的值为:\n");
printf("%s\n%d\n%s\n", e.a, e.b, e.c);
if (d.c != NULL) {
free(d.c);
d.c = NULL;
}
if (e.c != NULL) {
free(e.c);
e.c = NULL;
}
return 0;
}

偏移量的求法

1
2
3
4
5
6
struct note{
char name[64];
int age;
int sex;
}a,*p;
p=&a;

以p为例求p->age偏移量

直接法

1
int offsize = (int)&(p->age)-(int)p;

间接法

1
int offsize = (int)&(((*note)0)->age);

文章结束了,但我们的故事还在继续
坚持原创技术分享,您的支持将鼓励我继续创作!