在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