53

It is common to use {0} to initialize a struct or an array but consider the case when the first field isn't a scalar type. If the first field of struct Person is another struct or array, then this line will result in an error (error: missing braces around initializer).

struct Person person = {0};

At least GCC allows me to use an empty initializer list to accomplish the same thing

struct Person person = {};

But is this valid C code?

Also: Is this line guaranteed to give the same behavior, i.e. a zero-initialized struct?

struct Person person;
underscore_d
  • 6,309
  • 3
  • 38
  • 64
Marcus Ahlberg
  • 1,329
  • 2
  • 11
  • 24
  • C shouldn't guarantee initialization of anything except `static` variables, but I'm going off a single sentence in Wikipedia here. – millimoose Jul 11 '13 at 09:20
  • I might add that I built my code with GCC options pedantic and warnings-as-errors. Other compilers or configurations might allow the first syntax. – Marcus Ahlberg Jul 11 '13 at 09:21
  • Can you have a look at this: http://stackoverflow.com/questions/755305/empty-structure-in-c – NREZ Jul 11 '13 at 09:21
  • @NREZ: That's a different issue, being a struct with no members. – Hasturkun Jul 11 '13 at 09:28
  • 1
    @millimoose: variables that are explicitly initialized, even with empty braces, better had be guaranteed or something is badly broken! Local (auto) variables with an initializer are a different story though. – ams Jul 11 '13 at 09:30
  • @Hasturkun I was pointing out the different behavior of compilers for structures in C... – NREZ Jul 11 '13 at 09:40
  • Although this is a valid code `struct X{}; int main(){ struct X x = {}; return 1; }` Give it a try. – Grijesh Chauhan Jul 11 '13 at 09:41
  • @Bentoy13 VC++ does not support C99, so it is not a good compiler for this specific question. – Gorpik Jul 11 '13 at 10:22
  • 1
    @ams I was referring to the last line. I should've said "shouldn't guarantee implicit initialization" to be more specific. Obviously skipping explicit initialization would be ludicrous – millimoose Jul 11 '13 at 11:10
  • @millimoose & Gorpik: comment deleted; for all reasons, my comment is not pertinent – Bentoy13 Jul 11 '13 at 12:45
  • Related, and very useful: [How to initialize all members of an array to the same value?](https://stackoverflow.com/questions/201101/how-to-initialize-all-members-of-an-array-to-the-same-value/201116#201116). – Gabriel Staples Apr 06 '20 at 23:30

4 Answers4

64

No, an empty initializer list is not allowed. This can also be shown by GCC when compiling with -std=c99 -pedantic:

a.c:4: warning: ISO C forbids empty initializer braces

The reason is the way the grammar is defined in §6.7.9 of the 2011 ISO C Standard:

initializer:
         assignment-expression
         { initializer-list }
         { initializer-list , }
initializer-list:
         designation(opt) initializer
         initializer-list , designation(opt) initializer

According to that definition, an initializer-list must contain at least one initializer.

Geremia
  • 4,745
  • 37
  • 43
interjay
  • 107,303
  • 21
  • 270
  • 254
  • 5
    This is the correct answer (that an empty initializer-list is forbidden by the syntax). It's a bit unfortunate and it would be nice if the standards allowed it, but they don't really allow empty objects in general anyway, so it is not needed. The answer to the remaining part of the question (do you get as-if-zero if there is *no* `= {...}` part) is "yes if the object has static duration, no if not". – torek Jul 11 '13 at 09:35
  • 2
    This answers my question. I still don't have a fool-proof way of initializing the struct on a single line if I don't know the type of the first member (as is the case if the struct declaration is being auto-generated), but that is a different question. – Marcus Ahlberg Jul 11 '13 at 10:39
  • @MarcusAhlberg: Indeed the way the standard is set is very silly in this case. The author of that must have forgotten logic at home to allow specifying 1 to N initializers instead of 0 to N or, looking from the opposite direction omitting 0 to N-1 initializers instead of 0 to N. GCC does a great job of not enforcing it. – Pavel Šimerda Jun 05 '15 at 14:55
  • 1
    @torek: Not supporting empty objects (because you can't allocate and address them) and setting an artificial limit to omit only up to N-1 initializers instead of N resulting in absence of universal zero initializer are two very different things. – Pavel Šimerda Jun 05 '15 at 14:55
  • 1
    @PavelŠimerda: I'm confused by your comment: I didn't say empty initializers were not *useful*, just that they're not *required to exist*. If empty objects existed, then either they would need a special case ruling out initializers entirely (e.g., "empty objects may not be initialized") or they would require empty initializers. For that matter, allocating and addressing empty objects works fine in nonstandard GNU C, it just means that `&a==&b` is possible. – torek Jun 05 '15 at 18:49
15

Yes from C23 empty initialization is allowed. If the initializer is the empty initializer, the initial value is the same as the initialization of a static storage duration object.

struct Person person = {}; // Valid C23

If an object is initialized with an empty initializer, then:

  • If it has pointer type, it is initialized to a null pointer

  • If it has decimal floating type, it is initialized to (positive or unsigned) zero, and the quantum exponent is implementation-defined166)

  • If it has arithmetic type, and it does not have decimal floating type, it is initialized to (positive or unsigned) zero

  • If it is an aggregate, every member is initialized (recursively) according to these rules, and any padding is initialized to zero bits

  • If it is a union, the first-named member is initialized (recursively) according to these rules, and any padding is initialized to zero bit

Reference: ISO/IEC 9899:202x (E)

user16217248
  • 3,119
  • 19
  • 19
  • 37
Learner
  • 151
  • 1
  • 3
9

According to the C99 standard, array creation with an empty initializer list is forbidden. In a previous answer, you can see that grammar does not describe this case.


But what happens if you declare an array without initialization? Well, it depends on the compiler which you use. Let's take a look at this simple example: int arr[5] = {}.

GCC

By default gcc does not produce any warnings/errors when you try to compile this code. Not even -Wall, but -Wpedantic does.

warning: ISO C forbids empty initializer braces

But anyway gcc fill members of an array with 0's exactly as if you specify it explicitly int arr[5] = {0} see assembly output godbolt.

CLANG

But default not showing warnings about this case, but with option -Wgnu-empty-initializer does:

warning: use of GNU empty initializer extension

Clang generates different assembly code godbolt but behaves the same.

funnydman
  • 9,083
  • 4
  • 40
  • 55
  • The assembly code for Clang looks identical as well, perhaps it's something that has changed recently. – undercat Feb 26 '21 at 07:48
0

It depends. For ISO C standard, before ISO C23, the empty initialization of arrays, structs, or unions is not allowed; since ISO C23 (see 6.7.10 Initialization), it is allowed:

braced-initializer:
                    { }
                    { initializer-list }
                    { initializer-list , }

An empty brace pair ({}) is called an empty initializer and is referred to as empty initialization

However, GCC provides GNU C extensions that allow empty initialization of arrays or structs. Unless -Wpedantic, -pedantic, or -pedantic-errors options are given, GCC will not throw warnings or errors for this.

Ayka
  • 11
  • 1
  • 2