簡體   English   中英

在 C 中將一個結構分配給另一個

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM