5

我有以下代码。

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 的值并检查了。值是正确的。我想知道为什么上面的分配是错误的?如果错误,当您将结构变量传递给函数并将其捕获到单独的变量中时会发生什么?我希望我清楚我的问题。如果我不清楚我的问题,请回复我。

4

3 回答 3

9

在我看来,审稿人被误导了。非常正确,结构值和其他值一样,分配它们就可以了。而且它的方式,方式,比调用更清晰memcpy(),而且更(很多!)更不容易出错。

在复制相同类型的值时,我总是不得不停下来思考将什么作为第三个参数传递给memcpy()它,因为我发现哪个选择最清楚并不明显。所以,这是一个较少的教学问题,当然它读起来更好。

此外,编译器可能足够聪明,不会复制任何可能潜伏在那里的额外填充和/或对齐字节,这是memcpy()永远做不到的。这是一个更高级别的构造,因此“更好”。

于 2012-07-11T11:37:18.257 回答
4

它是,而且我认为一直是,有效的代码和你的评论是错误的。

在我看来,评论评论很糟糕,因为评论者误导你养成坏习惯——当我们想要复制任意内存位时,我们使用 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- 但执行速度更快。

所以总而言之,最初的审稿人是错的,而且仍然是错的,应该承认他们的错误——除非他们指的是他们可以证明的具体案例(我对此表示怀疑)

于 2012-07-11T11:37:29.027 回答
0

您的同事可能正在考虑一个数组,其中赋值语句无效。

由于数组和结构都作为聚合组合在一起,他可能认为同样的限制适用于结构类型的变量。

但是,请注意此分配与 C 中的相同memcpy,但不一定在 C++ 中(对于 POD 类型,它仍然相同)。这可能是编码标准禁止它的充分理由,在这种情况下,您应该遵循公司的编码标准。

于 2012-07-11T22:23:41.620 回答