memset() or value initialization to zero out a struct?
Those two constructs a very different in their meaning. The first one uses a memset
function, which is intended to set a buffer of memory to certain value. The second to initialize an object. Let me explain it with a bit of code:
Lets assume you have a structure that has members only of POD types ("Plain Old Data" - see What are POD types in C++?)
struct POD_OnlyStruct
{
int a;
char b;
};
POD_OnlyStruct t = {}; // OK
POD_OnlyStruct t;
memset(&t, 0, sizeof t); // OK as well
In this case writing a POD_OnlyStruct t = {}
or POD_OnlyStruct t; memset(&t, 0, sizeof t)
doesn't make much difference, as the only difference we have here is the alignment bytes being set to zero-value in case of memset
used. Since you don't have access to those bytes normally, there's no difference for you.
On the other hand, since you've tagged your question as C++, let's try another example, with member types different from POD:
struct TestStruct
{
int a;
std::string b;
};
TestStruct t = {}; // OK
{
TestStruct t1;
memset(&t1, 0, sizeof t1); // ruins member 'b' of our struct
} // Application crashes here
In this case using an expression like TestStruct t = {}
is good, and using a memset
on it will lead to crash. Here's what happens if you use memset
- an object of type TestStruct
is created, thus creating an object of type std::string
, since it's a member of our structure. Next, memset
sets the memory where the object b
was located to certain value, say zero. Now, once our TestStruct object goes out of scope, it is going to be destroyed and when the turn comes to it's member std::string b
you'll see a crash, as all of that object's internal structures were ruined by the memset
.
So, the reality is, those things are very different, and although you sometimes need to memset
a whole structure to zeroes in certain cases, it's always important to make sure you understand what you're doing, and not make a mistake as in our second example.
My vote - use memset
on objects only if it is required, and use the default initialization x = {}
in all other cases.
memset for initialization in C++
Don't use memset
. It's a holdover from C and won't work on non-PODs. Specifically, using it on a derived class that contains any virtual functions -- or any class containing a non-builtin -- will result in disaster.
C++ provides a specific syntax for initialization:
class A {
public:
A();
private:
int a;
float f;
char str[35];
long *lp;
};
A::A()
: a(0), f(0), str(), lp(NULL)
{
}
To be honest, I'm not sure, but memset
might also be a bad idea on floating-points since their format is unspecified.
Memset function in C initialised all the arrays
sizeof(pointer)
is the size of the entire array pointer
. Multiplying integers larger than 1 to that for size to memset()
will cause out-of-range access.
Remove the harmful multiplication.
int c = 15;
Struct *Pointer[c] /* = {NULL} */; /* VLA cannot be initialized */
/* some other code that uses Pointer */
memset(Pointer, 0, sizeof(Pointer));
How to initialize arrays in 2 ways using loop and memset?
A few points to help you get started:
- You're trying to set all items to
0
.Scanf
requires you to input all values. This isn't necessary as you could just set them to0
withdata[count]=0.0f;
inside of that for loop. memset
is a function that will do something similar for you (including the for loop). Have a look at the documentation ofmemset
:
memset
void * memset ( void * ptr, int value, size_t num );
Fill block of memory Sets the first num bytes of the block of memory
pointed by ptr to the specified value (interpreted as an unsigned
char).Parameters
- ptr:
Pointer to the block of memory to fill.- value:
Value to be set. The value is passed as an int, but the function fills the block of memory using the unsigned char conversion of this value.- num:
Number of bytes to be set to the value.
size_t is an unsigned integral type.
You should notice that memset only works with bytes. So you can use it to set a float to 0
, as it consists of 4 bytes that are all 0
, but you cannot set it to 1
for instance. But as notices by other users, this just happens to be so on most hardware.
history of memcpy and memset vs assignment and initialization
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.
Related Topics
Are C/C++ Fundamental Types Atomic
Getting a Bunch of Crosses Initialization Error
Automatic Copy Files to Output During Application Building
How to Pass an Std::String to Glshadersource
How to Install Tensorflow on Windows
How to Find the Qt5 Cmake Module on Windows
Command Line Compile Using Cl.Exe
Google Protocol Buffers on iOS
Does Scopeguard Use Really Lead to Better Code
How to Pan Images in Qgraphicsview
Implementing Future::Then() Equivalent for Asynchronous Execution in C++11
Treat C Cstyle Array as Std::Array
Compile Time String Encryption Using Constexpr
How to Do Aes Decryption Using Openssl
C++ Forwarding Reference and R-Value Reference
How to Force Gcc to Link Unreferenced, Static C++ Objects from a Library