[英]Assign one struct to another in C
您可以將結構的一個實例分配給另一個實例,如下所示:
struct Test t1;
struct Test t2;
t2 = t1;
我已經看到它適用於簡單的結構,但它適用於復雜的結構嗎?
編譯器如何知道如何根據類型復制數據項,即區分int
和 string?
是的,如果結構是相同類型的。 將其視為內存副本。
是的,結構支持賦值。 但是,存在以下問題:
struct S {
char * p;
};
struct S s1, s2;
s1.p = malloc(100);
s2 = s1;
現在兩個結構的指針都指向同一個內存塊——編譯器不會復制指向的數據。 現在很難知道哪個結構實例擁有數據。 這就是 C++ 發明用戶可定義賦值運算符概念的原因——您可以編寫特定代碼來處理這種情況。
首先看這個例子:
下面給出了一個簡單 C 程序的 C 代碼
struct Foo {
char a;
int b;
double c;
} foo1, foo2;
void foo_assign(void)
{
foo1 = foo2;
}
int main(/*char *argv[],int argc*/)
{
foo_assign();
return 0;
}
foo_assign() 的等效 ASM 代碼是
00401050 <_foo_assign>:
401050: 55 push %ebp
401051: 89 e5 mov %esp,%ebp
401053: a1 20 20 40 00 mov 0x402020,%eax
401058: a3 30 20 40 00 mov %eax,0x402030
40105d: a1 24 20 40 00 mov 0x402024,%eax
401062: a3 34 20 40 00 mov %eax,0x402034
401067: a1 28 20 40 00 mov 0x402028,%eax
40106c: a3 38 20 40 00 mov %eax,0x402038
401071: a1 2c 20 40 00 mov 0x40202c,%eax
401076: a3 3c 20 40 00 mov %eax,0x40203c
40107b: 5d pop %ebp
40107c: c3 ret
正如您所看到的,賦值在匯編中被簡單地替換為“mov”指令,賦值運算符僅表示將數據從一個內存位置移動到另一個內存位置。 分配只會對結構的直接成員執行此操作,並且當您在結構中具有復雜數據類型時將無法復制。 這里的 COMPLEX 意味着您不能擁有指向列表的指針數組。
結構中的字符數組本身在大多數編譯器上不起作用,這是因為賦值只會嘗試復制,甚至不會查看數據類型是否為復雜類型。
這是一個簡單的副本,就像您對memcpy()
所做的一樣(實際上,某些編譯器實際上會為該代碼生成對memcpy()
的調用)。 C 中沒有“字符串”,只有指向一堆字符的指針。 如果您的源結構包含這樣一個指針,那么指針將被復制,而不是字符本身。
您的意思是“復數”是指具有實部和虛部的復數嗎? 這似乎不太可能,所以如果不是,您必須舉一個例子,因為“復雜”在 C 語言方面沒有任何具體意義。
您將獲得結構的直接內存副本; 這是否是你想要的取決於結構。 例如,如果結構包含一個指針,則兩個副本將指向相同的數據。 這可能是也可能不是您想要的; 這取決於您的程序設計。
要執行“智能”復制(或“深度”復制),您需要實現一個函數來執行復制。 如果結構本身包含指針和包含指針的結構,並且可能包含指向此類結構的指針(也許這就是您所說的“復雜”),這可能很難實現,並且很難維護。 簡單的解決方案是使用 C++ 並為每個結構或類實現復制構造函數和賦值運算符,然后每個結構或類負責自己的復制語義,您可以使用賦值語法,並且更容易維護。
是的,您可以使用簡單的賦值語句將結構的一個實例分配給另一個實例。
在非指針或非指針包含結構成員的情況下,賦值意味着復制。
在指針結構成員的情況下,賦值意味着指針將指向另一個指針的相同地址。
讓我們親眼看看:
#include <stdio.h>
struct Test{
int foo;
char *bar;
};
int main(){
struct Test t1;
struct Test t2;
t1.foo = 1;
t1.bar = malloc(100 * sizeof(char));
strcpy(t1.bar, "t1 bar value");
t2.foo = 2;
t2.bar = malloc(100 * sizeof(char));
strcpy(t2.bar, "t2 bar value");
printf("t2 foo and bar before copy: %d %s\n", t2.foo, t2.bar);
t2 = t1;// <---- ASSIGNMENT
printf("t2 foo and bar after copy: %d %s\n", t2.foo, t2.bar);
//The following 3 lines of code demonstrate that foo is deep copied and bar is shallow copied
strcpy(t1.bar, "t1 bar value changed");
t1.foo = 3;
printf("t2 foo and bar after t1 is altered: %d %s\n", t2.foo, t2.bar);
return 0;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.