This is just a consequence of how the rules for initialisers are defined. If the current object of the initialisation is a struct
, union
or array, then if the next initialiser begins with a {
then the initialisers enclosed by that brace and its matching }
are used to initialise the members of that object; otherwise, it just marches through the list of initialisers, taking as many as it needs.
So, in the first case s1={{23,52},2.5}
, the current object starts out as s1.list
. This is an array, and the next initialiser is { 23, 52 }
, so that's used to initialise the array. s1.rate
is now the current object, and the next initialiser is 2.5
, so that works as expected.
In the second case s2={21,19,3.6}
, the current object starts out as s2.list
. This is an array, but the next initialiser does not start out with {
- so it takes as many values as it needs (in this case, two), and initialises the array with 21
and 19
. s2.rate
is now the current object, and the next initialiser is 2.5
, so again that works as expected.
In the third case v1={{23,52},2.5}
, the current object starts out as v1.list1
. This is a scalar, and the corresponding initialiser is {23, 52}
. This violates a constraint of the language - "The initializer for a scalar shall be a single expression, optionally enclosed in braces" - so that's why you get a warning. Formally the behaviour of your program is undefined, but it appears that your compiler just uses the first value contained in the initialiser and discards the excess ones. The current object is now v1.list2
, and the next initialiser is 2.5
, so the wrong value is used to initialise this member. There is no initialiser for v1.rate
; since v1
has static storage duration, this member is initialiser to 0.0
.
In the forth case v2={21,19,3.6}
, the current object starts out as v1.list1
, and the next initialiser is 21
- this value is used to initialise the member. After this the current object is v1.list2
and the next initialiser is 19
; then v1.rate
is the current object and the next initialiser is 3.6
.
For minimum confusion, you should always use a brace-enclosed initialiser for each struct
or array subobject.