I wasn't entirely happy with either option, so I asked around a bit for other ideas. I like the macro approach below, it gives us both self documentation and better checking for the size of the two structs.

Allison

-------- Original Message --------
From: Nick Forrette <[EMAIL PROTECTED]>
To: Allison Randal <[EMAIL PROTECTED]>

This can be a bit brittle -- you have to be careful when changing the
type of dst else you could end up with over or underflow.
memcpy(dst, src, sizeof(FOO));

I do like memcpy because it serves as a red flag that a potentially
medium to large size hunk of memory will be copied here,
memcpy(dst, src, sizeof(*dst));

This gets you better type checking (if src and dst are different
struct types, the compiler will complain). Much harder to overflow dst
or only partially copy src.
*dst = *src;


Something like this can get you the best of the above, as long as
you're careful about size-effects (I'd have to double check to be
sure, but I believe there are differences with pre-increment/decrement
in a dereference/assignment v.s. two arguments to a function).

#define copy_struct(dst, src) \
   (*(dst) = *(src))

copy_struct(dst, src);


You could use a more robust macro that does a run time check for size effects:

// returns int so it can be used in a , expression
int myAssert(int thisIsABool)
{
  assert(thisIsABool);
  return 0;
}

#ifdef NDEBUG
#define macro_assert(thisIsABool) 0
#else
#define macro_assert(thisIsABool) myAssert(thisIsABool)
#endif

#define copy_struct(dst, src) \
   (\
       macro_assert((dst) == (dst)), \
       macro_assert((src) == (src)), \
       (*(dst) = *(src)) \
   )


Gives you what I consider the best of all worlds. The compiler will
flag copying between different struct types, it is more robust in the
face of changed types for src or dst, in form that clearly spells out
what you're trying to do, that at least gives you run time checking
for abuse of side effects in debug builds.

Nick

Reply via email to