As you've already been told, trying to read values from uninitialized members of a structure leads to undefined behaviour. That is unconditionally bad. Therefore, it is incumbent upon you to ensure that all fields are initialized before they're read.
If you know all the elements of the structure and are going to initialize them explicitly, then the memset()
is not necessary. This can be manageable if the structure is under your control — you just have to remember to ensure that all the places where initialization takes place are updated when you add new members to the structure. If you write a function to do that (think 'C analogue of C++ constructor', to a first approximation), then the memset()
can be left out. If you set the values ad hoc in many places, you've probably got problems if the structure changes.
In the case of something like struct sigaction
, it is from a system-defined header, and different systems can (and do) add extra fields to the structure — over and above the ones you plan to initialize. Note that POSIX only specifies the fields that must be present; it does not dictate the order of the fields, nor does it mandate that there are no other fields in the structure. However, the functions using the extra (non-POSIX) elements of the structure should not do so unless the user indicates that those members are initialized, usually with some explicit flag, so you shouldn't run into problems — but it is better safe than sorry.
Consequently, in contexts where you don't have control over the structure, the memset()
approach is readily defensible: it is guaranteed to zero all of the structure, even the bits you don't know about — even if the structure definition changes (grows) after the code is written.
You may be able to use struct sigaction sa = { 0 };
or struct sigaction *sap = calloc(sizeof(*sap), 1);
to zero the structure instead — it depends in part on how fussy a set of compiler options you use (and also the version of the compiler you use; GCC has changed its behaviour over time, for example).
You might want to look up macros such as PTHREAD_MUTEX_INITIALIZER
in the POSIX standard — or you may prefer to ignore their existence altogether.