我有以下代码。
struct rectangle {
int length;
int breadth;
};
int main (void)
{
struct rectangle a,b;
a.length = 10;
a.breadth = 5;
b=a;
printf("\nValues of b.length = %d, b.breadth=%d\n",b.length,b.breadth);
return 0;
}
以上作业是否有效?(b = a)我在项目中这样做了。我收到了评论评论说明,此类作业错误,我应该使用memcpy 。我打印了b的值并检查了。值是正确的。我想知道为什么上面的任务是错的? 如果将结构变量传递给函数并将其捕获到单独的变量中会发生什么错误?我希望我的问题清楚。如果我对我的问题不清楚,请回复我。
答案 0 :(得分:8)
在我看来,审稿人是误入歧途的。这是非常正确的,结构值就像其他任何一样,分配它们就好了。它比调用memcpy()
更方便,更清晰,而且更多(更多!)不易出错。
我总是必须停下来思考在复制相同类型的值时作为memcpy()
的第三个参数传递的内容,因为我发现哪个选项最明显是不明显的。所以,这是一个较少的教学问题,当然它只是读得更好。
此外,编译器可能足够智能而不是来复制可能潜伏在那里的任何其他填充和/或对齐字节,memcpy()
永远不会做。它是一个更高级别的构造,因此“更好”。
答案 1 :(得分:4)
这是,我认为一直都是,有效的代码和您的评论评论错误。
在我看来,评论评论很糟糕,因为评论者误导你养成了坏习惯 - 当我们想要复制任意内存时我们使用memcpy - 根据定义,结构很明确,而且更清晰,更容易阅读,只是你的方式是对的。
如果将值按结构传递给函数,例如
struct a some_function(struct a)
{
a.width = 99;
return a;
}
传入的值是一个副本,返回值也是一个副本,这里唯一的危险是当结构很大并导致每次调用的开销时。
如果这不起作用,那么C世界的大部分都会崩溃......
为了接受评论者的评论,我认为他们正在深入挖掘整体,应该承认错误。
两个陈述之间没有区别
memcpy(&b, &a, sizeof(b));
b = a;
如果编译器正在优化,那么它不应该破坏原始代码;否则这是编译器中的一个错误 - 它是hokum提到原始的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
版本的大小完全相同 - 但执行速度会更快。
总而言之,原始审稿人错了,仍然错了,应该承认错误 - 除非他们指的是他们可以证明的具体案例(我怀疑)
答案 2 :(得分:0)
您的同事可能正在考虑一个数组,其中赋值语句无效。
由于数组和结构都被组合在一起作为聚合,他可能认为同样的限制适用于struct类型的变量。
但请注意,此分配与C中的memcpy
相同,但不一定在C ++中(对于POD类型,它仍然相同)。这可能是编码标准禁止它的充分理由,在这种情况下,您应该遵循公司的编码标准。