Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Assigning a const-string to a constant sized char array, what happens in un-used array indices?

Tags:

c++

c++11

Let's say I have:

char name[16] = "123456789abc";

so name[11] == 'c', name[12] == '\0'.

Will name[13] be gibberish/compiler-dependant, or will it reliably be a specific value (such as '\0'?)

like image 614
Wolfgang Skyler Avatar asked Dec 29 '25 08:12

Wolfgang Skyler


1 Answers

When a character array is initialized from a string literal, unused elements are initialized to zero.

Section 8.5.2 has the rule:

An array of narrow character type (3.9.1), char16_t array, char32_t array, or wchar_t array can be initialized by a narrow string literal, char16_t string literal, char32_t string literal, or wide string literal, respectively, or by an appropriately-typed string literal enclosed in braces (2.14.5). Successive characters of the value of the string literal initialize the elements of the array.

There shall not be more initializers than there are array elements.

If there are fewer initializers than there are array elements, each element not explicitly initialized shall be zero-initialized (8.5).

Therefore, they will be zero. Guaranteed.

And accessing them is not undefined behavior.


If you initialized from a list of characters instead char name[16] = { '1', '2', '3', '4', '5', 0 };, you'd be in the realm of aggregate initialization, which gives the same result through a different route.

When aggregate initialization is used and there are fewer initializers than elements of the aggregate, the remainder are value initialized (unless there is a brace-or-equal-initializer in the definition of the aggregate type).

The rule is found in section 8.5.1

An initializer-list is ill-formed if the number of initializer-clauses exceeds the number of members or elements to initialize.

If there are fewer initializer-clauses in the list than there are members in the aggregate, then each member not explicitly initialized shall be initialized from its brace-or-equal-initializer or, if there is no brace-or-equal-initializer, from an empty initializer list (8.5.4).

And there is an example given:

struct  S  {  int  a;  const  char*  b;  int  c;  int  d  =  b[a];  };
S  ss  =  {  1,  "asdf"  };

initializes ss.a with 1, ss.b with "asdf", ss.c with the value of an expression of the form int{} (that is, 0), and ss.d with the value of ss.b[ss.a] (that is, 's')


C++03 didn't explicitly state that extra elements would be zero-initialized in the character array rule. On the other hand the aggregate rule was substantially similar and did guarantee value initialization, always (brace-or-equal-initializer was introduced in C++11).

C99 section 6.7.8 provides zero initialization in both cases, to wit:

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.

Of course, objects with static storage duration are pre-initialized to zero.

like image 157
Ben Voigt Avatar answered Jan 01 '26 00:01

Ben Voigt



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!