I have the following code.
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;
}
Is the above assignment a valid statement?(b=a) I did it this way inside my project. I got a review comment stating, this type of assignment is wrong and i should have done used memcpy. I printed the values of b and checked. The values are correct. I was wondering why the above assignment is wrong? If it is wrong what happens when you pass a structure variable to a function and catch it in a separate variable? I hope i am clear on my question. Please get back to me if i am unclear on my question.
The reviewer is, in my opinion, misguided. It's very correct, struct values are just like any other, it's just fine to assign them. And it's way, way, clearer than invoking memcpy()
, and much (much!) less error-prone.
I always have to stop and think about what to pass as the third argument to memcpy()
when copying the same type of value, since I find it non-obvious which choice is the clearest. So, that's one less pedagogical problem, and of course it just reads better.
Also, the compiler might be smart enough not to copy any additional padding and/or alignment bytes that might lurk in there, something memcpy()
can never do. It's a higher-level construct, and thus "simply better".
It is, and I think always has been, valid code and your review comment is wrong.
In my view the review comment is bad because the reviewer is misleading you into bad habits - we use memcpy when we want to copy arbitrary bits of memory - and by definition a struct is well defined and it's cleaner, easier to read, and simply your way is right.
If you pass a struct by value to a function, e.g.
struct a some_function(struct a)
{
a.width = 99;
return a;
}
The value passed in is a copy, and the return value is also a copy, the only danger here is when the struct is big and results in an overhead for each call.
If this didn't work then most of the C world would fall apart...
To take onboard the reviewers comments, in my opinion they are digging themselves deeper into a whole and should just admit being wrong.
There is no difference between the two statements
memcpy(&b, &a, sizeof(b));
b = a;
If a compiler is optimising then it shouldn't break the original code; otherwise that's a fault in the compiler - it's hokum mentioning the original C standard (i.e. C89) as I doubt very much that the standard permits faulty optimisation.
For interest, rather than proof of anything I just tried this on a pre-ansi compiler (from 1986) in a standard unix environment.
/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
For further interest, maybe only mine! I've built with optimisation and looked at the generated code.
The results show that this ancient, pre standard compiler works as expected. The proof in 68k is below - I've added comments with // to explain what's happening.
As you can see, the only result of optimising is that the generated code is more efficient both in terms of space and also execution time - not that that matters much unless you're working in an embedded environment
; 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
for a larger struct the code generated for b=a
is
170 LEA (-112,FP),A1
174 LEA (-224,FP),A0
178 MOVEQ #27,D0
180 MOVE.L (A1)+,(A0)+
182 DBF D0,main+60
which is exactly the same size as the memcpy
version - but will execute faster.
So in summary the original reviewer was wrong and is still wrong and should admit their mistake - unless they are referring to a specific case that they can prove (which I doubt)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With