结构mystruct a=b;这有效吗?结构变量的直接赋值,在C语言中有效吗?

结构mystruct a=b;这有效吗?结构变量的直接赋值,在C语言中有效吗?,c,coding-style,C,Coding Style,我有以下代码 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; } 上述作业是有效

我有以下代码

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的值并进行了检查。这些值是正确的。我想知道为什么上面的作业是错的如果将结构变量传递给函数并在单独的变量中捕获时发生了什么错误?我希望我的问题清楚。如果我对我的问题不清楚,请与我联系。

我认为审稿人被误导了。这是非常正确的,结构值和其他值一样,分配它们也很好。而且它比调用
memcpy()
更清晰,而且更不容易出错

当复制同一类型的值时,我总是不得不停下来思考将什么作为第三个参数传递给
memcpy()。所以,这是一个较少的教学问题,当然它读起来更好


此外,编译器可能足够聪明,不会复制任何可能隐藏在其中的额外填充和/或对齐字节,
memcpy()。它是一个更高层次的构造,因此“简单地说是更好的”。

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

在我看来,评论是不好的,因为评论者误导你养成了坏习惯——当我们想要复制任意内存位时,我们使用memcpy——根据定义,结构是定义良好的,它更干净、更容易阅读,而且简单地说,你的方式是正确的

如果您通过值将结构传递给函数,例如

struct a some_function(struct a)
{
    a.width = 99;
    return a;
}
传入的值是一个副本,返回值也是一个副本,这里唯一的危险是结构太大,导致每次调用的开销

如果这不起作用,那么C世界的大部分都会崩溃

在我看来,要接受评论家们的评论,他们是在更深入地了解一个整体,应该承认自己错了

这两种说法没有区别

memcpy(&b, &a, sizeof(b));
b = a;
如果编译器正在优化,那么它不应该破坏原始代码;否则这就是编译器中的一个错误——这是胡言乱语,提到了原始的C标准(即C89),因为我非常怀疑该标准是否允许错误的优化

出于兴趣,我只是在标准unix环境中的一个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
版本大小完全相同,但执行速度更快


因此,总而言之,最初的审阅者是错误的,现在仍然是错误的,应该承认他们的错误——除非他们指的是能够证明(我怀疑)的具体案例

您的同事可能想到了一个数组,其中赋值语句无效

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


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

您的代码确实无效,但这是由于
main
签名,而不是分配。您能告诉我主签名有什么问题吗?main应该返回int(除非:blabala)有一个用于“独立实现”的“除非”。第二个签名应该是
intmain(void)
intmain(void)
int main()
不是签名。它用1986年的编译器编译并不意味着什么。@akappa是的,我想说的是,我记得这在ANSI C89之前就一直有效,我想检查一下。@wildplasser void main()错误的评论也是有效的…结构赋值一直是合法的。VLA可能是C99中的一个例外。(就像struct hack一样)请查找我在unwinds Solution上提供的注释,我刚刚与审阅者进行了核对。他提到,给出审查意见是因为,如果结构中有一个指针,那么这个过程将变得复杂。这个有效期有多远?他指出的另一件事是,编译器正在优化赋值,但根据原始的C标准和遵循这些标准的编译器,这种赋值是错误的。@happy2Help:我认为他有点困惑,因为他说的没有任何意义:A)因此他同意作业是有效的C,但是如果你想要一份深度副本,它就不起作用。是的,但是在这种情况下memcpy都不够,因为赋值和memcpy在语义上是等价的。顺便说一句,你想要浅拷贝还是深拷贝?你一开始就有指针吗?B) 您正在针对该语言的特定版本编写代码。你是为C89/C99还是为一些古老的前ANSI C而写?我认为答案是显而易见的,所以他的话显然是愚蠢的。指针式的论点显然是假的。这是abo