So, my understanding is that the following code:
somestruct_t a = {0};
somestruct_t b;
b = a;
is always preferable, when possible, to:
somestruct_t a;
somestruct_t b;
memset(&a, 0, sizeof(a));
memcpy(&b, &a, sizeof(a));
And the top constructs are almost always possible...which leads me to my question: Since the top code both performs well, and is to me clearly more intuitive to someone learning the language, why are the memset
and memcpy
patterns so amazingly prevalent in C and even non-OO C++ code? Literally every project I've worked on for decades prefers the bottom pattern.
I'm assuming there is some historical reason for it, such as very old compilers not supporting it or somesuch, but I'd very much like to know the specific reason.
I know general history questions are off-topic, but this is about a very specific bad practice that I would like to understand better.
EDIT I am NOT trying to assert that memcpy and memset are bad in general. I'm talking about a very specific use pattern of assignment or initialization of a single structure.
It sounds like your experience is significantly different from mine, and from several of the other commentators here.
I don't know anyone who prefers
memcpy(&a, &b, sizeof(a));
over
a = b;
In my programming world (and in just about any world I can imagine), simple assignment is vastly preferable to memcpy
. memcpy
is for moving chunks of arbitrary data around (analogous to strcpy
, but when it's arbitrary bytes instead of null-terminated strings). It's hard to imagine why anyone would advocate using memcpy
instead of struct assignment. Naturally there are individual programmers everywhere who have gotten into various bad habits, so I guess I can't be too surprised if there are some who prefer the opposite, but I have to say, I would generally disagree with what they're doing.
Someone speculated in the comments that there was perhaps some historical precedent at work, but at least for the memcpy
-versus-assignment questions, I can state with some certainty that this is not the case.
Once upon a time, before there was C90 memcpy
, there was BSD bcopy
, but before there was bcopy
there wasn't a standard function for doing an efficient copy of a bunch of bytes from point a to point b. But there was struct assignment, which really has been in the language almost from the beginning. And struct assignment typically uses a nice, tight, compiler-generated byte-copying loop. So there was a time when it was fashionable to do something like this:
#define bcpy(a, b, n) (*(struct {char x[n];} *)a = *(struct {char x[n];} *)b)
I may have gotten the syntax wrong, but this hijacks the compiler's ability to do efficient struct assignment, and repurposes it to copy n
bytes from arbitrary pointer b
to arbitrary pointer a
, i.e. just like bcopy
or memcpy
.
In other words, it's not like memcpy
came first, followed by struct assignment -- it was actually exactly the opposite!
Now, memset
versus struct initialization is a different story.
Most of the "clean" ways of zeroing a struct are initializations, but of course it's not uncommon to want to set a struct to all zero at some point later than when it was defined. It's also not uncommon to have a dynamically-allocated struct, and using malloc
/realloc
rather than calloc
. So in those cases, memset
is attractive. I think modern C has struct constants you can use at any time, but I'm guessing I'm not the only one who still hasn't learned them and so is still tending to use memset
instead.
So I wouldn't consider using memset
to be poor style, not in the same way as memcpy
is poor style for struct assignment.
Although I have seen, and written, code that did something like
struct s zerostruct = { 0 };
and then later
a = zerostruct;
as a "better style" alternative to
memset(&a, 0, sizeof(a));
Bottom line: I wouldn't agree that memcpy
is recommended over struct assignment, and I am critical of anyone who prefers it. But memset
is quite useful (and not disrecommended) for zeroing structures, because the alternatives aren't nearly as compelling.
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