在C语言中结构体变量之间可以进行赋值操作吗?
简单结构体的赋值
先说结论:一般来说,C语言中的结构体变量可以用另一个变量对其进行赋值或初始化。简单结构体(不包含指针成员)直接赋值没有问题。
我们先下面一段代码:
#include
#include
struct MyStruct
{
int a;
int b;
char c[10];
};
int main()
{
struct MyStruct t1 = {1, 2, "hello"};
struct MyStruct t2 = {3, 4, "world"};
t2 = t1; //将t1赋值给t2
printf("MyStruct t1: %d, %d, %s\n", t1.a, t1.b, t1.c);
printf("MyStruct t2: %d, %d, %s\n", t2.a, t2.b, t2.c);
return 0;
}
以上代码的输出为:
MyStruct t1: 1, 2, hello
MyStruct t2: 1, 2, hello
以上用t1给t2进行初始化,结果也相同。可以看到简单的结构体(结构体的成员没有指针成员)变量之间直接赋值是没有问题的。
有指针成员的结构体赋值
而通常情况下,稍微复杂一点的结构体里面会有指针成员,那么以上的浅拷贝则会有问题了,我们假设MyStruct里面的成员c不是数组,而是字符指针,会有什么问题呢? 看如下代码:
#include
#include
#include
struct MyStruct
{
int a;
int b;
char* c;
};
int main()
{
struct MyStruct t1;
t1.a = 1;
t1.b = 2;
// 为指针区域赋值
char *p = (char*)malloc(10*sizeof(char));
strcpy(p, "hello");
t1.c = p;
struct MyStruct t2;
t2 = t1;
printf("MyStruct t1: %d, %d, %s\n", t1.a, t1.b, t1.c);
// 释放了t1的内存
// free(p);
printf("MyStruct t2: %d, %d, %s\n", t2.a, t2.b, t2.c);
printf("t1 pointer addr: %p\n", t1.c);
printf("t2 pointer addr: %p\n", t2.c);
return 0;
}
上面的输出结果为:
MyStruct t1: 1, 2, hello
MyStruct t2: 1, 2, hello
t1 pointer addr: 0x6000284d0
t2 pointer addr: 0x6000284d0
可以看到,赋值会直接将t1的指针变量赋值给t2.c,如果我们在赋值之后将t1所用的资源释放掉,那么使用t2的话则可能导致内存泄漏了。如果上面的代码,我们没有注释掉 free(p);,那么输出t2时结果这不确定了:
MyStruct t1: 1, 2, hello
MyStruct t2: 1, 2, (/.?
t1 pointer addr: 0x6000284d0
t2 pointer addr: 0x6000284d0
所以,如果struct中有指针成员,那么结构体赋值不能简单的直接复制了,而需要为指针成员另外分配内存,并将数据拷贝过去,当然我们可以将这些处理封装在单独的函数中来完成。 示例代码如下:
#include
#include
#include
struct MyStruct
{
int a;
int b;
char* c;
};
int main()
{
struct MyStruct t1;
t1.a = 1;
t1.b = 2;
// 为指针区域赋值
char *p = (char*)malloc(10*sizeof(char));
strcpy(p, "hello");
t1.c = p;
struct MyStruct t2;
// 各个成员分别赋值,可以进行封装
t2.a = t1.a;
t2.b = t1.b;
char *p2 = (char*)malloc(10*sizeof(char));
strcpy(p2, t1.c);
t2.c = p2;
printf("MyStruct t1: %d, %d, %s\n", t1.a, t1.b, t1.c);
// 释放了t1的内存
free(p);
printf("MyStruct t2: %d, %d, %s\n", t2.a, t2.b, t2.c);
// 释放了t2的内存
free(p2);
printf("t1 pointer addr: %p\n", t1.c);
printf("t2 pointer addr: %p\n", t2.c);
return 0;
}
以上代码输出结果为:
MyStruct t1: 1, 2, hello
MyStruct t2: 1, 2, hello
t1 pointer addr: 0x6000284d0
t2 pointer addr: 0x600062e10