167

If I have a struct like this:

typedef struct
{
    unsigned char c1;
    unsigned char c2;
} myStruct;

What would be the easiest way to initialize this struct to 0? Would the following suffice?

myStruct _m1 = {0};

or Would I need to explicitly init each member to 0?

myStruct _m2 = {0,0};
200_success
  • 7,286
  • 1
  • 43
  • 74
Daan Timmer
  • 14,771
  • 6
  • 34
  • 66
  • 1
    Note: if the structure has padding bytes (due to alignment), then neither of these guarantee that they are initialized. It may be important when writing the structure to external storage, network or comparing with `memcmp`. In such cases one should use `memset`. – Yakov Galka Jan 29 '21 at 03:18

4 Answers4

185

The first is easiest(involves less typing), and it is guaranteed to work, all members will be set to 0[Ref 1].
The second is more readable.

The choice depends on user preference or the one which your coding standard mandates.

[Ref 1] Reference C99 Standard 6.7.8.21:

If there are fewer initializers in a brace-enclosed list than there are elements or members of an aggregate, or fewer characters in a string literal used to initialize an array of known size than there are elements in the array, the remainder of the aggregate shall be initialized implicitly the same as objects that have static storage duration.

Good Read:
C and C++ : Partial initialization of automatic structure

Community
  • 1
  • 1
Alok Save
  • 202,538
  • 53
  • 430
  • 533
  • 13
    Also, I am using `= {};` However I am not sure if this is valid. – William Entriken Mar 19 '15 at 21:09
  • 24
    @FullDecent empty braces for initialization is a GNU extension. – a3f Sep 12 '15 at 18:13
  • 1
    Is this also true for pointers? Is zero-initialization the same as null-initialization in the case of `char *` (for example)? – rvk Oct 05 '16 at 14:30
  • 2
    It is not purely a mater of preference - maintainability plays a role. If the structure changes (members added or removed) the `_m2` example makes less sense if there were more members, and would have to be updated if the number of members decreased. – Clifford Apr 04 '17 at 10:29
  • 1
    @a3f according to [cppreference](http://en.cppreference.com/w/cpp/language/value_initialization), empty braces for initialization is a standard since c++11. – jv-dev Jul 21 '17 at 17:26
  • 5
    @alias65536 The question is tagged C not C++. – a3f Jul 21 '17 at 17:27
  • 4
    I got an error: "missing braces around initializer [-Werror=missing-braces]" probably because of an member array :/ – jaques-sam Feb 14 '18 at 11:07
  • for better readability, `#define ZERO_FULL {0}` or `#define ZERO_ALL {0}` – Edenia Jun 17 '18 at 08:59
  • 17
    @Edenia. I disagree. I already know what `foo = {0}` means. If I saw `foo = ZERO_FULL`, I'd have to grep for the definition of ZERO_FULL. – Andrew Bainbridge Jul 24 '18 at 14:51
  • 2
    I think to be explicit in your answer, you should add **"And `objects that have static storage duration` are initialized to zero. Therefore, any members of a struct not mentioned in a brace-enclosed list shall be automatically initialized to zero."** – Gabriel Staples Jun 20 '19 at 23:33
  • `myStruct _m1 = {0};` doesn't work in C++. :( `error: cannot initialize a member subobject of type 'myScope::MyStructType' with an rvalue of type 'int'`. How do you zero-initialize a struct in C++? – Gabriel Staples Apr 15 '20 at 23:59
  • Figured it out: remove the zero: `myStruct _m1 = {};` – Gabriel Staples Apr 16 '20 at 00:01
  • I made it a separate Q&A: https://stackoverflow.com/questions/61240589/initializing-a-struct-to-0-in-c/61240590#61240590 – Gabriel Staples Apr 16 '20 at 00:08
  • struct foo bar = {}; is valid since C23, and zeroes bar entirely. It is already supported by a number of recent compilers like gcc, clang. OTOH, struct foo bar = {0}; will work on older compilers that don't support C23 or this small subset of it as an extension. – anonymous Jan 03 '23 at 13:50
45

If the data is a static or global variable, it is zero-filled by default, so just declare it myStruct _m;

If the data is a local variable or a heap-allocated zone, clear it with memset like:

memset(&m, 0, sizeof(myStruct));

Current compilers (e.g. recent versions of gcc) optimize that quite well in practice. This works only if all zero values (include null pointers and floating point zero) are represented as all zero bits, which is true on all platforms I know about (but the C standard permits implementations where this is false; I know no such implementation).

You could perhaps code myStruct m = {}; or myStruct m = {0}; (even if the first member of myStruct is not a scalar).

My feeling is that using memset for local structures is the best, and it conveys better the fact that at runtime, something has to be done (while usually, global and static data can be understood as initialized at compile time, without any cost at runtime).

Basile Starynkevitch
  • 223,805
  • 18
  • 296
  • 547
  • 12
    There's no guarantee that setting all bytes of the struct to `0` will be equivalent to initializing all struct members with `0` though. On many platforms this will be true, but not universally. – Sander De Dycker Jun 22 '12 at 07:55
  • 3
    Can you share an example, Sander? Genuine curiosity. (Obviously, not universally true doesn't necessarily mean there's an easy-to-explain exception, but if there is...) – Steven Fisher Jun 22 '12 at 07:57
  • 2
    The *C* standard permits the null pointer (or a zero floating point number) to be represented in memory by something else than all zero bits. Very few and weird implementations are doing that (I cannot name any). – Basile Starynkevitch Jun 22 '12 at 07:59
  • 2
    -1, you might find the initialization that the OP asks about ugly, but it is exactly what is forseen by the standard and that can be easily optimized by all compilers. Then, the form `{}` is not valid C but only available in C++. – Jens Gustedt Jun 22 '12 at 08:08
  • 9
    @Steven : I can only think of obscure and/or old platforms. The C FAQ has a list of platforms that had a `NULL` pointer that wasn't all `0` bits : http://c-faq.com/null/machexamp.html. And then there's the possibility the platform is not using IEEE 754 to represent floating point values, but uses some other representation that doesn't have an all `0` bit `0.0` value - but admittedly I know of no such platform. – Sander De Dycker Jun 22 '12 at 08:32
  • I came across this while searching, so probably worth pointing out that as of GCC 8.1 there's a warning for doing this on an object with "no trivial copy-assignment" – LordAro May 13 '18 at 16:12
  • -1, it doesn't matter if the first member of a struct is non-scalar; the nested braces can be omitted according to the standard. – Garogolun Oct 30 '18 at 13:19
  • 1
    In the case where your struct contains sub-arrays, it seems that `= {0}` as recommended by the main answer does not work, so you *must* use the `memset()` technique you show here. The error I got trying the `= {0}` technique for my struct which contains sub-arrays was: `error: suggest braces around initialization of subobject [-Werror,-Wmissing-braces]` – Gabriel Staples Jun 13 '19 at 21:31
  • 1
    `= {}` is not allowed in Standard C , and `= { 0 }` is a valid initializer for all possible structs. If the first member is an aggregate then it applies to the first member of that aggregate etc. , according to the brace elision rules – M.M Feb 17 '21 at 21:14
  • 1
    @GabrielStaples The `= { 0 }` initializes all members correctly; you have used flags which render your compiler non-conforming. – M.M Feb 17 '21 at 21:15
  • @M.M could you add a reference for those brace elision rules? I was actually looking for them. – alx - recommends codidact Sep 14 '21 at 10:48
  • 1
    @alx see C11 6.7.9/20, the sentence starting "Otherwise" describes what happens when the subobject didn't have a braced initializer (e.g. `0`), and this applies recursively as per the first sentence of that paragraph; and then once that `0` is consumed, 6.7.9/21 kicks in and everything else is zero-initialized – M.M Sep 14 '21 at 20:19
23

See §6.7.9 Initialization:

21 If there are fewer initializers in a brace-enclosed list than there are elements or members of an aggregate, or fewer characters in a string literal used to initialize an array of known size than there are elements in the array, the remainder of the aggregate shall be initialized implicitly the same as objects that have static storage duration.

So, yes both of them work. Note that in C99 a new way of initialization, called designated initialization can be used too:

myStruct _m1 = {.c2 = 0, .c1 = 1};
Cœur
  • 37,241
  • 25
  • 195
  • 267
dirkgently
  • 108,024
  • 16
  • 131
  • 187
  • 1
    Most notably this is already C89: http://www.open-std.org/JTC1/SC22/WG14/www/docs/n1124.pdf#page=139 (Important for specific signal processing targets) – Tobias Jul 02 '19 at 14:55
  • But note that it works intuitively for {0} but not as clear if you for example do {1}. It's easy to think that it would set everything to 1, but it will set only the first to 1 and implicitly initialise the rest so you likely end up with 1,0. – Zitrax Feb 12 '21 at 11:39
  • And in C23 you can do myStruct _m1 = {}; – anonymous Jan 03 '23 at 13:52
11

I also thought this would work but it's misleading:

myStruct _m1 = {0};

When I tried this:

myStruct _m1 = {0xff};

Only the 1st byte was set to 0xff, the remaining ones were set to 0. So I wouldn't get into the habit of using this.

DuDa
  • 3,718
  • 4
  • 16
  • 36
pgibbons
  • 309
  • 2
  • 5
  • 3
    The question explicitly asks about initializing the structure elements to 0, and also, the quickest way to do it. So, for initializing the elements with some other value, you must use the traditional method – sukhbir1996 Oct 20 '21 at 05:13
  • 1
    Thank you for stating the obvious. It is still misleading because when someone looks up assignment, they might not want to set something to 0 but to something else, and they would see this method and might try to use it. I'm not sure if you understand where I'm coming from at all but I tried to explain it. – pgibbons Dec 06 '21 at 16:10