我知道我可以按成员复制结构成员,而不是我可以在结构上进行memcpy
吗?
建议这样做吗?
在我的结构中,我有一个字符串也作为成员,我必须复制到具有相同成员的另一个结构。我该怎么做?
答案 0 :(得分:61)
通过简单分配进行复制是最好的,因为它更短,更容易阅读,并且具有更高的抽象级别。而不是(向代码的人类读者)说“将这些位从这里复制到那里”,并要求读者考虑副本的大小参数,你只是做一个简单的赋值(“复制这个值来自在这里“)。关于尺寸是否正确,可以毫不犹豫。
此外,如果结构被大量填充,则赋值可能会使编译器发出更高效的内容,因为它不必复制填充(并且它知道它在哪里),但mempcy()
不会所以它总是会复制你告诉它复制的确切字节数。
如果你的字符串是一个实际的数组,即:
struct {
char string[32];
size_t len;
} a, b;
strcpy(a.string, "hello");
a.len = strlen(a.string);
然后你仍然可以使用普通作业:
b = a;
获取完整副本。对于这样建模的可变长度数据,这不是执行复制的最有效方法,因为整个数组将始终被复制。
请注意,复制包含指向堆分配内存的指针的结构可能有点危险,因为这样做会使别名指针,并且通常会使拥有指针的模糊不清复制操作后。
对于这些情况,“深层复制”确实是唯一的选择,而且需要进入功能。
答案 1 :(得分:37)
从C90开始,您只需使用:
dest_struct = source_struct;
只要字符串存储在数组中:
struct xxx {
char theString[100];
};
否则,如果是指针,则需要手动复制。
struct xxx {
char* theString;
};
dest_struct = source_struct;
dest_struct.theString = malloc(strlen(source_struct.theString) + 1);
strcpy(dest_struct.theString, source_struct.theString);
答案 2 :(得分:15)
如果结构是兼容的类型,是的,你可以使用类似的东西:
memcpy (dest_struct, source_struct, sizeof (*dest_struct));
您唯一需要注意的是这是一个浅副本。换句话说,如果您有char *
指向特定字符串,两个结构将指向相同的字符串。
更改其中一个字符串字段的内容(char *
指向的数据,而不是char *
本身)也会改变另一个字段。
如果您想要一个简单的副本,而不必手动完成每个字段,但需要额外的非浅字符串副本,请使用strdup
:
memcpy (dest_struct, source_struct, sizeof (*dest_struct));
dest_struct->strptr = strdup (source_struct->strptr);
这将复制结构的全部内容,然后深层复制字符串,有效地为每个结构提供单独的字符串。
并且,如果您的C实现没有strdup
(它不是ISO标准的一部分),get one from here。
答案 3 :(得分:4)
你可以memcpy
结构,或者你可以像任何其他值一样分配它们。
struct {int a, b;} c, d;
c.a = c.b = 10;
d = c;
答案 4 :(得分:1)
在C语言中,memcpy仅具有极高的风险。只要您使所有三个参数完全正确,结构成员都不是指针(或者,您明确打算进行浅表复制),并且结构中没有大的对齐间隙,因此memcpy会浪费时间循环(或性能无关紧要),那么绝对是memcpy。除了难于阅读的代码,对将来的更改脆弱而且必须在代码审查中手动验证(因为编译器无法进行)的代码之外,您什么都没有得到。但是,嘿,可以肯定为什么不这样做。
在C ++中,我们前进到可笑的风险。您可能具有无法安全处理的类型的成员,例如std :: string,这将导致您的接收结构成为危险的武器,每次使用时都会随机破坏内存。在模拟分片副本时,您可能会意外涉及虚拟函数。该优化器可以为您做奇妙的事情,因为它在编译=时具有完整类型知识的保证,而对memcpy调用则无济于事。
在C ++中,有一个经验法则-如果看到memcpy或memset,则出了点问题。在少数情况下,这是不正确的,但它们不涉及结构。您只有在有理由盲目复制字节时才使用memcpy。
另一方面,赋值易于阅读,在编译时检查正确性,然后在运行时智能地移动值。没有缺点。
答案 5 :(得分:0)
您可以使用结构读取写入文件。 您不需要将其强制转换为`char *。 结构尺寸也将保留。 (这一点并不是最接近主题但猜测它: 在硬记忆上行为通常类似于RAM记忆。)
要移动(到和来自)单个字符串字段,您必须使用strncpy
和一个瞬态字符串缓冲区'\0'
终止。
在某处你必须记住记录字符串字段的长度。
要移动其他字段,您可以使用点符号,例如:
NodeB->one=intvar;
floatvar2=(NodeA->insidebisnode_subvar).myfl;
struct mynode {
int one;
int two;
char txt3[3];
struct{char txt2[6];}txt2fi;
struct insidenode{
char txt[8];
long int myl;
void * mypointer;
size_t myst;
long long myll;
} insidenode_subvar;
struct insidebisnode{
float myfl;
} insidebisnode_subvar;
} mynode_subvar;
typedef struct mynode* Node;
...(main)
Node NodeA=malloc...
Node NodeB=malloc...
您可以将每个字符串嵌入适合它的结构中,
避开点-2并表现得像科博尔:
NodeB->txt2fi=NodeA->txt2fi
...但你仍然需要一个瞬态字符串
在strncpy
,scanf
的第2点加上一printf
加(NodeB->insidenode_subvar).mypointer=(NodeA->insidenode_subvar).mypointer
否则操作员输入更长(更短),
不会被截断(用空格填充)。
NodeB.txt3=NodeA.txt3
将创建一个指针别名。error: incompatible types when assigning to type ‘char[3]’ from type ‘char *’
导致编译器拒绝:
NodeB->txt2fi
point-4仅适用于NodeA->txt2fi
& typedef
属于同一个[my_section title="Foo" the_id="123"][my_text]my example text[/my_text][/my_section]
!!
我找到的这个主题的正确而简单的答案 In C, why can't I assign a string to a char array after it's declared? "阵列(也是角色)是C"中的二等公民; !!!
答案 6 :(得分:0)
您可以使用以下解决方案来实现您的目标:
struct student
{
char name[20];
char country[20];
};
void main()
{
struct student S={"Wolverine","America"};
struct student X;
X=S;
printf("%s%s",X.name,X.country);
}