2

Consider copy a simple struct which doesn't require special copy semantics.

struct A
{
    char i
    int i;
    long l;
    double b;
    //...maybe more member
}
struct A a;
a.c = 'a'; //skip other member just for illustrate
struct A b;
memset(&a, 0, sizeof(a));
b.c = a.c;
//...for other members, the first way to assign
memcpy(&b, &a, sizeof(b)); //the second way
b = a;    //the third way

The 3 methods do the same thing, and it seems all of them are correct. I used to use 'memcpy' for copying simple structs, but seems now '=' can do the same thing. So is there any difference between using memcpy and '='?

Baum mit Augen
  • 49,044
  • 25
  • 144
  • 182
A Lan
  • 425
  • 3
  • 10
  • 2
    `memcpy` will copy the padding between members. – Barmar Mar 20 '14 at 03:28
  • `memset` : memset(addres of object, set char, size) – BLUEPIXY Mar 20 '14 at 03:29
  • @Barmar And `=` may or may not; it's up to the implementation. – Jim Balter Mar 20 '14 at 03:31
  • It does not seem to be fixed. – BLUEPIXY Mar 20 '14 at 03:31
  • @Barmar, you mean for the reason of memory aligned, memcpy copy and padding but '=' will not? – A Lan Mar 20 '14 at 03:31
  • The difference between those three ways, I guess, depends on the structure to be copied and the programming language you are using. – Lee Duhem Mar 20 '14 at 03:31
  • 1
    `memcpy()` can also be convenient for copying an array of structs in one go. – Dmitri Mar 20 '14 at 03:33
  • @Dmitri, yes, agree with that point about copy array. tks. – A Lan Mar 20 '14 at 03:39
  • With floating point NaN, I do not think that `a = b` must _always_ give the same bit-for-bit copy. Further `memcpy()` forces a variable to exist in memory and not a register. – chux - Reinstate Monica Mar 20 '14 at 03:39
  • Depending on your definition of simple, you might be violating `memcpy`'s contract. For example, having a `std::string` member will not need a deep copy, yet `memcpy` will not be a good idea. – chris Mar 20 '14 at 03:41
  • @chux Copying a NaN must certainly result in the same NaN. And I wouldn't worry about structs in registers. – Jim Balter Mar 20 '14 at 03:42
  • @Jim Balter 1) Could not a signaling NaN invoke a handler just by doing the `a = b` assignment? Of course a `memcpy()` would not. 2) are not structures of diminutive size allowed to be passed in registers? – chux - Reinstate Monica Mar 20 '14 at 03:45
  • @chux a) I'm not sure but I think signaling NaNs only raise exceptions when operands of arithmetic operators, not assignment -- but if they do raise exceptions, you won't get any sort of copy at all; if they are copied, it will be bit-for-bit. b) Yes, they can be; I just said I wouldn't worry about them. – Jim Balter Mar 20 '14 at 03:52
  • @Jim Balter In general about (a), I agree that bit-for-bit copy is the usual & expected, but with FP types ([80-bit double Pseudo Denormal](http://en.wikipedia.org/wiki/Extended_precision#x86_Extended_Precision_Format) and [decimal base](http://en.wikipedia.org/wiki/Decimal64_floating-point_format) ) there are sometimes multiple bit representations for the same value & a copy going though some Math processor may emit a preferred one. All somewhat esoteric situations. C rarely defines this detail & I suspect the door is open for `a = b` results in the same value, but differing bit patterns. – chux - Reinstate Monica Mar 20 '14 at 04:11

3 Answers3

8

memcpy treats the structure as a contiguous array of bytes, and just copies all of them. As a result, it will always copy the padding bytes after members.

= is only required to copy the members. It might or might not copy the padding.

Barmar
  • 741,623
  • 53
  • 500
  • 612
  • tks, Barmar, is that means '=' is the same as b.c = a.c ...etc? – A Lan Mar 20 '14 at 03:37
  • Yes, that's the required semantics. It might be optimized into different code -- the compiler could turn it into something like `memcpy`. – Barmar Mar 20 '14 at 03:38
1

Any of the three methods -- manually assigning each member, assigning the entire struct, or using memcpy -- will result in all the members of b being the same as the corresponding members of a, which is all you should care about. The potential differences are in the value of pad bytes -- memcpy will copy them, assigning individual members won't, and assigning the entire struct may or may not -- it's up to the implementation. Some implementations will just use memcpy to assign structs, some will assign member by member, and some will do one or the other depending on such factors as the size of the struct.

I recommend using struct assignment -- it's the simplest, the shortest, and the most problem-oriented. Leave the implementation details up to the compiler. Also, in C++ you can define the assignment operator yourself for greater control and flexibility, and memcpy is frowned on and can have bad effects with classes (see JaredPar's answer).

Jim Balter
  • 16,163
  • 3
  • 43
  • 66
  • 1
    @JasonC The list is the OP's, who is asking about C (but is interested in programming in C++ in the future). And the copy constructor won't necessarily result in the members of `b` being the same as the members of `a`, unlike the other three methods. – Jim Balter Mar 20 '14 at 03:45
1

I would get in the habit now of using = instead of memcpy. In C the difference is minimal at best but once you graduate to C++, as indicated by the question, the difference is huge. Consider for example

struct C {
  C() { }
  ~C() { } 
}

C local1;
C local2;
memcpy(&local2, &local1, sizeof(C));

In this case the the constructor for local2 is run at the declaration point. However the destructor for that value is never run. Instead it's members are magically replaced with memcpy and the destructor is run on the memcpy bits. If C happened to allocate any resources this can easily lead to leaks.

JaredPar
  • 733,204
  • 149
  • 1,241
  • 1,454