繁体   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