它是,而且我认为一直是,有效的代码和你的评论是错误的。
在我看来,评论评论很糟糕,因为评论者误导你养成坏习惯——当我们想要复制任意内存位时,我们使用 memcpy——根据定义,结构定义明确,它更干净、更容易阅读,而且只是你的方法是对的。
如果您将结构按值传递给函数,例如
struct a some_function(struct a)
{
a.width = 99;
return a;
}
传入的值是一个副本,返回值也是一个副本,这里唯一的危险是结构体很大并且每次调用都会产生开销。
如果这不起作用,那么大多数 C 世界都会分崩离析......
为了接受审稿人的评论,在我看来,他们正在更深入地挖掘自己的整体,应该承认自己错了。
两种说法没有区别
memcpy(&b, &a, sizeof(b));
b = a;
如果编译器正在优化,那么它不应该破坏原始代码;否则那是编译器的一个错误——它提到了原始的 C 标准(即 C89)是胡说八道,因为我非常怀疑该标准是否允许错误的优化。
出于兴趣,我只是在标准 unix 环境中的 pre-ansi 编译器(从 1986 年开始)上尝试过这个,而不是证明任何东西。
/tmp> gcc a.c
a.c:
C-68000U 1.8.0 Copyright (c)1985,1986 Green Hills Software, Inc.
linking a:
/tmp> ./a
10, 5
为了进一步的兴趣,也许只有我的!我已经通过优化构建并查看了生成的代码。
结果表明,这个古老的、预标准的编译器按预期工作。68k 的证明如下 - 我用 // 添加了注释来解释正在发生的事情。
如您所见,优化的唯一结果是生成的代码在空间和执行时间方面都更高效——除非您在嵌入式环境中工作,否则这并不重要
; line #13 memcpy(&b, &a, sizeof(b));
140 PEA 0x8 // size
144 PEA (-8,FP) // &a
148 PEA (-16,FP) // &b
152 JSR memcpy // call memcpy
; line #14
170 LEA (-8,FP),A1 // &a
174 LEA (-16,FP),A0 // &b
178 MOVE.L (A1)+,(A0)+ // copy first element of struct
180 MOVE.L (A1)+,(A0)+ // copy second element
对于更大的结构,生成的代码b=a
是
170 LEA (-112,FP),A1
174 LEA (-224,FP),A0
178 MOVEQ #27,D0
180 MOVE.L (A1)+,(A0)+
182 DBF D0,main+60
它的大小与版本完全相同memcpy
- 但执行速度更快。
所以总而言之,最初的审稿人是错的,而且仍然是错的,应该承认他们的错误——除非他们指的是他们可以证明的具体案例(我对此表示怀疑)