C语言 将一种结构复制到另一种结构
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4931123/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Copying one structure to another
提问by asir
I know that I can copy the structure member by member, instead of that can I do a memcpyon structures?
我知道我可以逐个复制结构成员,而不是我可以对结构进行复制memcpy吗?
Is it advisable to do so?
这样做是否可取?
In my structure, I have a string also as member which I have to copy to another structure having the same member. How do I do that?
在我的结构中,我也有一个字符串作为成员,我必须将其复制到具有相同成员的另一个结构中。我怎么做?
回答by unwind
Copying by plain assignment is best, since it's shorter, easier to read, and has a higher level of abstraction. Instead of saying (to the human reader of the code) "copy these bits from here to there", and requiring the reader to think about the size argument to the copy, you're just doing a plain assignment ("copy this value from here to here"). There can be no hesitation about whether or not the size is correct.
通过普通赋值复制是最好的,因为它更短、更容易阅读并且具有更高的抽象级别。而不是说(对代码的人类读者)“从这里复制这些位到那里”,并要求读者考虑复制的大小参数,你只是在做一个简单的赋值(“从从这里到这里”)。对于尺寸是否正确,可以毫不犹豫。
Also, if the structure is heavily padded, assignment might make the compiler emit something more efficient, since it doesn't have to copy the padding (and it knows where it is), but mempcy()doesn't so it will always copy the exact number of bytes you tell it to copy.
此外,如果结构被大量填充,赋值可能会使编译器发出更有效的东西,因为它不必复制填充(并且它知道它在哪里),但mempcy()它不会复制确切的数字你告诉它复制的字节数。
If your string is an actual array, i.e.:
如果您的字符串是实际数组,即:
struct {
char string[32];
size_t len;
} a, b;
strcpy(a.string, "hello");
a.len = strlen(a.string);
Then you can still use plain assignment:
然后你仍然可以使用普通赋值:
b = a;
To get a complete copy. For variable-length data modelled like this though, this is not the most efficient way to do the copy since the entire array will always be copied.
得到一个完整的副本。但是,对于像这样建模的可变长度数据,这不是进行复制的最有效方法,因为将始终复制整个数组。
Beware though, that copying structs that contain pointers to heap-allocated memory can be a bit dangerous, since by doing so you're aliasingthe pointer, and typically making it ambiguous who owns the pointer after the copying operation.
但请注意,复制包含指向堆分配内存的指针的结构可能有点危险,因为这样做会使指针别名,并且通常会在复制操作后使谁拥有该指针变得不明确。
For these situations a "deep copy" is really the only choice, and that needs to go in a function.
对于这些情况,“深拷贝”确实是唯一的选择,并且需要在函数中进行。
回答by Simone
Since C90, you can simply use:
从 C90 开始,您可以简单地使用:
dest_struct = source_struct;
as long as the string is memorized inside an array:
只要字符串存储在数组中:
struct xxx {
char theString[100];
};
Otherwise, if it's a pointer, you'll need to copy it by hand.
否则,如果它是一个指针,则需要手动复制它。
struct xxx {
char* theString;
};
dest_struct = source_struct;
dest_struct.theString = malloc(strlen(source_struct.theString) + 1);
strcpy(dest_struct.theString, source_struct.theString);
回答by paxdiablo
If the structures are of compatible types, yes, you can, with something like:
如果结构是兼容的类型,是的,您可以使用以下内容:
memcpy (dest_struct, source_struct, sizeof (*dest_struct));
The only thing you need to be aware of is that this is a shallowcopy. In other words, if you have a char *pointing to a specific string, bothstructures will point to the same string.
您唯一需要注意的是,这是一个浅拷贝。换句话说,如果您有一个char *指向特定字符串的指针,则两个结构都将指向同一个字符串。
And changing the contents of one of those string fields (the data that the char *points to, not the char *itself) will change the other as well.
更改这些字符串字段之一的内容(char *指向的数据,而不是其char *本身)也会更改另一个。
If you want a easy copy without having to manually do each field but with the added bonus of non-shallow string copies, use strdup:
如果您想要一个简单的副本,而不必手动执行每个字段,但具有非浅字符串副本的额外好处,请使用strdup:
memcpy (dest_struct, source_struct, sizeof (*dest_struct));
dest_struct->strptr = strdup (source_struct->strptr);
This will copy the entire contents of the structure, then deep-copy the string, effectively giving a separate string to each structure.
这将复制结构的全部内容,然后深度复制字符串,有效地为每个结构提供一个单独的字符串。
And, if your C implementation doesn't have a strdup(it's not part of the ISO standard), get one from here.
而且,如果您的 C 实现没有strdup(它不是 ISO 标准的一部分),请从这里获取。
回答by Conrad Meyer
You can memcpystructs, or you can just assign them like any other value.
您可以memcpy构造,也可以像分配任何其他值一样分配它们。
struct {int a, b;} c, d;
c.a = c.b = 10;
d = c;
回答by Scott M
In C, memcpy is only foolishly risky. As long as you get all three parameters exactly right, none of the struct members are pointers (or, you explicitly intend to do a shallow copy) and there aren't large alignment gaps in the struct that memcpy is going to waste time looping through (or performance never matters), then by all means, memcpy. You gain nothing except code that is harder to read, fragile to future changes and has to be hand-verified in code reviews (because the compiler can't), but hey yeah sure why not.
在 C 中, memcpy 只是愚蠢的冒险。只要您完全正确地获得所有三个参数,结构成员都不是指针(或者,您明确打算进行浅拷贝)并且结构中没有大的对齐间隙,memcpy 将浪费时间循环(或性能无关紧要),那么无论如何,memcpy。除了更难阅读的代码、对未来更改的脆弱性以及必须在代码中手动验证(因为编译器不能)之外,您一无所获,但是嘿,是的,为什么不呢。
In C++, we advance to the ludicrously risky. You may have members of types which are not safely memcpyable, like std::string, which will cause your receiving struct to become a dangerous weapon, randomly corrupting memory whenever used. You may get surprises involving virtual functions when emulating slice-copies. The optimizer, which can do wondrous things for you because it has a guarantee of full type knowledge when it compiles =, can do nothing for your memcpy call.
在 C++ 中,我们前进到可笑的冒险。您可能拥有不安全的 memcpyable 类型的成员,例如 std::string,这将导致您的接收结构成为危险武器,在使用时随机破坏内存。在模拟切片副本时,您可能会遇到涉及虚函数的惊喜。优化器可以为您做一些奇妙的事情,因为它在编译 = 时保证了完整的类型知识,但它对您的 memcpy 调用没有任何作用。
In C++ there's a rule of thumb - if you see memcpy or memset, something's wrong. There are rare cases when this is not true, but they do not involve structs. You use memcpy when, and only when, you have reason to blindlycopy bytes.
在 C++ 中,有一个经验法则——如果你看到 memcpy 或 memset,那就有问题了。在极少数情况下这不是真的,但它们不涉及结构。当且仅当您有理由盲目复制bytes时,您才使用 memcpy 。
Assignment on the other hand is simple to read, checks correctness at compile time and then intelligently moves valuesat runtime. There is no downside.
另一方面,赋值很容易阅读,在编译时检查正确性,然后在运行时智能地移动值。没有缺点。
回答by Anvesh
You can use the following solution to accomplish your goal:
您可以使用以下解决方案来实现您的目标:
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);
}
回答by splugenbrau
You can use a struct to read write into a file. You do not need to cast it as a `char*. Struct size will also be preserved. (This point is not closest to the topic but guess it: behaving on hard memory is often similar to RAM one.)
To move (to & from) a single string field you must use
strncpyand a transient string buffer'\0'terminating. Somewhere you must remember the length of the record string field.To move other fields you can use the dot notation, ex.:
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...You can embed each string into a structs that fit it, to evade point-2 and behave like Cobol:
NodeB->txt2fi=NodeA->txt2fi...but you will still need of a transient string plus onestrncpyas mentioned at point-2 forscanf,printfotherwise an operator longer input (shorter), would have not be truncated (by spaces padded).(NodeB->insidenode_subvar).mypointer=(NodeA->insidenode_subvar).mypointerwill create a pointer alias.NodeB.txt3=NodeA.txt3causes the compiler to reject:error: incompatible types when assigning to type ‘char[3]' from type ‘char *'point-4 works only because
NodeB->txt2fi&NodeA->txt2fibelong to the sametypedef!!A correct and simple answer to this topic I found at In C, why can't I assign a string to a char array after it's declared?"Arrays (also of chars) are second-class citizens in C"!!!
您可以使用结构来读取写入文件。您不需要将其转换为 `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 点并表现得像 Cobol:
NodeB->txt2fi=NodeA->txt2fi...但您仍然需要一个临时字符串加上第strncpy2 点中提到的一个forscanf,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 *'第 4 点有效只是因为
NodeB->txt2fi&NodeA->txt2fi属于同一个typedef!!我在In C 中找到的这个主题的正确而简单的答案 ,为什么我不能在声明后将字符串分配给 char 数组?“数组(也是字符)是 C 中的二等公民”!!!

