Memset () or value initialization to nullify a structure?

In Win32 API programming, it is typical to use a C struct with multiple fields. Usually only a couple of them have significant values, and all the rest should be reset to zero. This can be achieved in one of two ways:

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

or

 STRUCT theStruct = {}; 

The second option looks cleaner - it is single-line, it does not have any parameters that can be clouded and lead to an error.

Does it have flaws compared to the first option? Which option to use and why?

+46
c ++ c initialization struct visual-c ++
Jan 04 '10 at 10:40
source share
8 answers

These two designs are very different in meaning. The first uses the memset function, which is designed to set the memory buffer to a specific value. The second is to initialize the object. Let me explain this with code:

Suppose you have a structure in which there are only members of POD types

 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, the entry POD_OnlyStruct t = {} or POD_OnlyStruct t; memset(&t, 0, sizeof t) POD_OnlyStruct t; memset(&t, 0, sizeof t) doesn't really matter, since the only difference we have here is alignment bytes set to zero if memset used. Since you do not have access to these bytes, there is no difference.

On the other hand, since you marked your question as C ++, try a different example, with member types other than 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 memset on it will fail. Here, what happens if you use memset - an object of type TestStruct is created, thus creating an object of type std::string , since it is a member of our structure. Then memset sets the memory in which the object b was at a certain value, for example, zero. Now, as soon as our TestStruct object goes out of scope, it will be destroyed, and when the queue comes to it, the member std::string b you will see a failure, since all the internal structures of this object were destroyed by memset .

So, the reality is that these things are very different, and although in some cases you sometimes need a memset whole structure for zeros, it is always important to make sure that you understand what you are doing and not doing as in our second example.

My vote - use memset for objects only if necessary, and use the default initialization x = {} in all other cases.

+70
Jan 04 '10 at 16:42
source share

Depending on the members of the structure, these two options are not necessarily equivalent. memset set the structure to all bits-zero, while initializing the values ​​will initialize all members to zero. The C standard guarantees that they will be the same only for integral types, and not for floating point values ​​or pointers.

In addition, some APIs require that the structure really be set to all bits-zero. For example, the Berkeley socket API uses structures polymorphically, and there it is important to really set the entire structure to zero, not just the values ​​that are obvious. The API documentation should indicate whether the structure should really be full-bit-zero, but it may be insufficient.

But if none of them or a similar case applies, then it is up to you. When defining the structure, I would prefer to initialize the value, since this more clearly conveys the intention. Of course, if you need to nullify an existing structure, memset is the only choice (well, except initializing each member to zero manually, but this usually does not work, especially for large structures).

+28
Jan 04 '10 at
source share

If your structure contains things like:

 int a; char b; int c; 

Then padding bytes will be inserted between "b" and "c". memset () will be null, there will be no other way, so there will be 3 bytes of garbage (if your ints are 32 bits). If you intend to use your structure to read / write from a file, this may be important.

+10
Jan 04
source share

I would use value initialization because it looks clean and less error prone, as you mentioned. I do not see a lack of this.

You can rely on memset to nullify the structure after using it.

+6
Jan 04 '10 at
source share

not that it is generic, but, I think, the second way also has the advantage of initializing the float to zero. If you do memset, of course, not

+5
Jan 04 '10 at
source share

On some STRUCT theStruct = {}; compilers STRUCT theStruct = {}; translates to memset( &theStruct, 0, sizeof( STRUCT ) ); into an executable file. Some C functions are already associated with tuning the runtime, so the compiler has these library functions, such as memset / memcpy, available for use.

+3
Jan 04 '10 at
source share

Initializing the value, as it can be done at compile time.
Also, it correctly initializes 0 all types of POD.

The memset () function is executed at runtime.
Also, the use of memset () is suspicious if the structure is not a POD.
It does not correctly initialize (to zero) non int types.

+2
Jan 04 '10 at 10:52
source share

If there are many pointer elements, and you are likely to add more in the future, this may help to use memset. In combination with the corresponding calls to assert(struct->member) you can avoid accidental crashes by trying to read a bad pointer that you forgot to initialize. But if you are not so forgotten as I am, then the initialization of the members is probably the best!

However , if your structure is used as part of a public API, you must get the client code to use memset as a requirement. This helps with future validation, because you can add new members, and the client code automatically cancels them in the memset call, instead of leaving them in a (possibly dangerous) uninitialized state. This is what you do when working with socket structures, for example.

-one
Jan 04 '10 at 11:08
source share



All Articles