是的,如果结构属于同一类型。将其视为内存副本。
是的,结构支持赋值。但是,也有问题:
struct S {
char * p;
};
struct S s1, s2;
s1.p = malloc(100);
s2 = s1;
现在两个结构的指针都指向同一个内存块——编译器不会复制指向的数据。现在很难知道哪个结构实例拥有数据。这就是 C++ 发明用户可定义赋值运算符概念的原因——您可以编写特定代码来处理这种情况。
struct
本身的数据被清楚地复制了。
首先看这个例子:
下面给出了一个简单的 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”指令,赋值运算符只是意味着将数据从一个内存位置移动到另一个内存位置。分配只会对结构的直接成员执行此操作,并且当结构中有复杂数据类型时将无法复制。这里的复杂意味着你不能有指针数组,指向列表。
结构中的字符数组本身不适用于大多数编译器,这是因为赋值将简单地尝试复制,甚至无需查看数据类型是否为复杂类型。
这是一个简单的副本,就像您对 memcpy()
所做的那样(事实上,一些编译器实际上会为该代码生成对 memcpy()
的调用)。 C中没有“字符串”,只有指向一堆字符的指针。如果您的源结构包含这样的指针,那么指针会被复制,而不是字符本身。
memcpy
,请参见此处:godbolt.org/z/nPxqWc - 但是现在如果我传递相同的指针 a
和 b
,并且 *a = *b
被转换为未定义行为的 memcpy
,因为对于 memcpy
“内存区域不能重叠。” (引用手册页)。那么编译器在使用 memcpy
时是错误的,还是我在编写这样的作业时是错误的?
您的意思是“复数”,即具有实部和虚部的复数吗?这似乎不太可能,所以如果不是,您必须举一个例子,因为“复杂”在 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;
}
不定期副业成功案例分享