你能否将一个结构实例分配给另一个结构,如下所示:
struct Test t1;
struct Test t2;
t2 = t1;
我看到它适用于简单的结构,它是否适用于复杂的结构?
编译器如何知道如何根据类型复制数据项,即区分int
和字符串?
答案 0 :(得分:132)
如果结构属于同一类型,则为是。将其视为记忆副本。
答案 1 :(得分:124)
是的,结构支持赋值。但是,有一些问题:
struct S {
char * p;
};
struct S s1, s2;
s1.p = malloc(100);
s2 = s1;
现在两个结构的指针指向同一块内存 - 编译器不会复制指向的数据。现在很难知道哪个struct实例拥有数据。这就是为什么C ++发明了用户可定义的赋值运算符的概念 - 你可以编写特定的代码来处理这种情况。
答案 2 :(得分:22)
首先看一下这个例子:
下面给出了简单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意味着你不能指向列表的指针数组。
结构中的一个字符数组本身在大多数编译器中都不起作用,这是因为赋值只会尝试复制而不会将数据类型视为复杂类型。
答案 3 :(得分:15)
这是一个简单的副本,就像你使用memcpy()
一样(实际上,有些编译器实际上会为该代码调用memcpy()
)。 C中没有“字符串”,只有指向一堆字符的指针。如果您的源结构包含这样的指针,那么指针将被复制,而不是字符本身。
答案 4 :(得分:6)
您的意思是“复杂”是否与复数有实部和虚部?这似乎不太可能,所以如果不是,你必须举一个例子,因为“复杂”意味着没有具体的C语言。
您将获得结构的直接内存副本;这是否是你想要的取决于结构。例如,如果结构包含指针,则两个副本将指向相同的数据。这可能是也可能不是你想要的;这取决于你的程序设计。
要执行“智能”复制(或“深层”复制),您需要实现一个功能来执行复制。如果结构本身包含也包含指针的指针和结构,并且可能指向这样的结构(可能就是“复杂”的意思),这可能很难实现,而且很难维护。简单的解决方案是使用C ++并为每个结构或类实现复制构造函数和赋值运算符,然后每个都负责自己的复制语义,您可以使用赋值语法,并且更容易维护。
答案 5 :(得分:0)
是的,您可以使用简单的赋值语句将结构的一个实例分配给另一个实例。
在非指针或非指针包含结构体成员的情况下,赋值意味着复制。
在指针结构成员的情况下,赋值意味着指针将 指向另一个指针的相同地址。
让我们亲眼看看:
$array | Foreach-Object {
$_ | Select ($_.psobject.Properties | Where Value).Name
} | Format-List