Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

memset() or value initialization to zero out a struct?

In Win32 API programming it's typical to use C structs with multiple fields. Usually only a couple of them have meaningful values and all others have to be zeroed out. This can be achieved in either of the two ways:

STRUCT theStruct; memset( &theStruct, 0, sizeof( STRUCT ) ); 

or

STRUCT theStruct = {}; 

The second variant looks cleaner - it's a one-liner, it doesn't have any parameters that could be mistyped and lead to an error being planted.

Does it have any drawbacks compared to the first variant? Which variant to use and why?

like image 814
sharptooth Avatar asked Jan 04 '10 10:01

sharptooth


People also ask

How do you initialize a struct to NULL?

You can't. NULL is a pointer whose value is set to zero, but your mark and space properties are not pointer values. In your code as you have it, they will both be value types, allocated as part of your Pair struct. Change the variables to Segment * instead of Segment , and you will be able to set them to NULL.

How do you initialize a structure?

An initializer for a structure is a brace-enclosed comma-separated list of values, and for a union, a brace-enclosed single value. The initializer is preceded by an equal sign ( = ).

How do you initialize a struct variable in C++?

// In C++ We can Initialize the Variables with Declaration in Structure. Structure members can be initialized using curly braces '{}'. For example, following is a valid initialization.


1 Answers

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.

like image 157
Dmitry Avatar answered Sep 18 '22 12:09

Dmitry