7

I was just reading about a library called sofia-sip and this line appeared in a code sample:

msg_iovec_t iovec[2] = {{ 0 }};

For reference, here is the definition of msg_iovec_t:

struct iovec {
    void *iov_base;     // Pointer to data.
    size_t iov_len;     // Length of data.
};
bloudermilk
  • 17,820
  • 15
  • 68
  • 98
  • 2
    Highly off-topic, but isn't the "_t" suffix reserved for POSIX types and its highly discouraged to attach it to your own type names? – JustSid Mar 20 '11 at 11:40
  • 2
    @JustSid – [Yes](http://pubs.opengroup.org/onlinepubs/9699919799/functions/V2_chap02.html#tag_15_02_02) and [maybe](http://stackoverflow.com/questions/1186072/naming-scheme-for-typedefs/1186143#1186143). – aaz Mar 20 '11 at 17:41

2 Answers2

8

This creates an array of two iovec structures on the stack and initializes all members of both array elements to zero.

The initializer {{ 0 }} only gives an explicit value for the first member of the first array element: iovec[0].iov_base. The supplied value 0 is converted implicitly to a null pointer.

The other members of the first array element and the other array elements are also initialized, implicitly: pointers to null and arithmetic types to 0.

The line can be written equivalently as

msg_iovec_t iovec[2] = { 0 };

This is the shortest standard way to zero-initialize an entire object, so it is idiomatic. Some compilers might accept an empty initializer list {} as an extension. Some compilers might issue a warning for this form and require enough braces to designate the first non-aggregate member (two pairs as in the original line).

The effect is similar to

msg_iovec_t iovec[2];
bzero(iovec, sizeof iovec);

except cleaner and portable, because a pointer filled with zero bytes is not necessarily a null pointer.

aaz
  • 5,136
  • 22
  • 18
  • +1, the point here being that everything is zeroed out, not just the iov_base field of the first element. – ig2r Mar 20 '11 at 12:13
  • 1
    A reason for having a zero inside, is that historically not all compilers have agreed on what is "sufficient". – Bo Persson Mar 20 '11 at 13:38
  • 1
    Also `bzero(&myptr, sizeof(myptr));` isn't the same as `myptr = 0;` (`myptr = NULL;`). – Conrad Meyer Mar 20 '11 at 14:09
  • 1
    @aaz: `{}` is **not valid C**. It's C++ only. `{0}` is the shortest universal zero initializer in C. – R.. GitHub STOP HELPING ICE Mar 20 '11 at 15:12
  • Thanks. @Bo, @R. – you're right, the grammar demands a non-empty list (though `gcc` accepts it without `-pedantic`). @Conrad – that's what I meant by "similar" – clarified. – aaz Mar 20 '11 at 16:42
  • 2
    The reason you see the double braces in the code is that GCC authors managed to damage the support of universal zero initializer idiom `{ 0 }` by issuing warnings when it is used to initialize multi-level aggregates (like an array of structs). Normally one'd use just `{ 0 }`, but because of the warnings one has to use `{{ 0 }}`. – AnT stands with Russia Mar 20 '11 at 16:49
  • @AndreyT – That explains the original line, thanks. I think the best way to deal with those warnings is the same as for the "suggest parentheses around `&&`" ones – with `-Wno-missing-braces`. – aaz Mar 20 '11 at 17:21
2

First bracket declares that array is being initialized. The second declares that structure's iovec first field: iov_base is being initialized by NULL value

Dewfy
  • 23,277
  • 13
  • 73
  • 121