8

Suppose the following initialization:

char mystr[4] = "";

Does the C99 standard guarantee that a character array initialized to an empty string will initialize all elements in the character array to null bytes? For example, does the standard guarantee that mystr[2] == '\0'?

How about these initializations:

char myfoo[4] = { '\0' };
char mybar[4] = { 0 };

While I'm pretty certain that explicitly setting the first element of a character array will guarantee the implicit initialization of the rest of the elements to 0, I suspect a string literal initialization results in a copy to the array -- thus meaning a single \0 is copied to the array while the remaining elements are left uninitialized.

3 Answers 3

12

Section 6.7.8, paragraph 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.

And how are objects with static storage duration initialized?

Section 6.7.8, paragraph 10:

If an object that has automatic storage duration is not initialized explicitly, its value is indeterminate. If an object that has static storage duration is not initialized explicitly, then:

  • if it has pointer type, it is initialized to a null pointer;
  • if it has arithmetic type, it is initialized to (positive or unsigned) zero;
  • if it is an aggregate, every member is initialized (recursively) according to these rules;
  • if it is a union, the first named member is initialized (recursively) according to these rules.

char is an arithmetic type, so it's initialized to 0. Huzzah, you can rest easy.

Sign up to request clarification or add additional context in comments.

Comments

6

C language follows "all or nothing" approach to all aggregate initializations. It means that any attempt to supply an explicit initializer for any part of the aggregate (regardless of how small that part is) immediately guarantees that the entire aggregate will be initialized. The parts without an explicit initializer will be zero-initialized.

In your example the entire array is guaranteed to be initialized with zeros. In case of struct initialization, all fields that are not initialized explicitly get zero values.

One consequence of that principle is that in C language the = { 0 } initializer serves as an idiomatic universal zero initializer. Since the language allows = { value } syntax in scalar object initializers as well, one can use = { 0 } to initialize any object to all-zero state

#define UNIVERSAL_ZERO { 0 }

double d = UNIVERSAL_ZERO;
char s[100] = UNIVERSAL_ZERO;
struct { int x, y, z; } xyz = UNIVERSAL_ZERO;
int *p = UNIVERSAL_ZERO;

4 Comments

That's a good point, I never thought of doing that to initialize things other than arrays. Is there any disadvantage to doing this as opposed to, say, memset(&xyz, 0, sizeof(xyz));
@Taylor Brandstetter: Theoretically, = { 0 } is different. It initializes the data with proper type-dependent 0 values. For example, if some platform uses 0xFFFFFFFFF pattern to represent null pointers, the = { 0 } will actually produce the proper 0xFFFFFFFFF representation. Your memset, on the other hand, will just fill everything with all-zero bit pattern. For another example, if some platform uses non-zero bit pattern to represent floating 0.0 value, the = { 0 } will properly produce that representation, while your memset will, again, just fill everything with zeros.
Granted, in practice platforms that use non-zero bit pattern to represent zero values are rare and/or exotic. On a typical everyday platform memset achieves the same effect as = { 0 } and, most likely, generates the same code.
Also, = { 0 } is not guaranteed to intialize padding areas that might be present in the aggregate, while memset will just zero out everything. This might matter in some cases. And it doesn't matter in others.
4

Yes, excess elements of an array are always zero-initialized, and arrays of char initialized using a string literal are no exception either.

From the C99 Standard, section 6.7.8.21 (page 139 of this document):

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.