The C standard states (emphasize mine):
21 EXAMPLE 2 After the declaration:
struct s { int n; double d[]; };
the structure struct
s
has a flexible array memberd
. [...]
22 Following the above declaration:
struct s t1 = { 0 }; // valid struct s t2 = { 1, { 4.2 }}; // invalid t1.n = 4; // valid t1.d[0] = 4.2; // might be undefined behavior
The initialization of
t2
is invalid (and violates a constraint) becausestruct s
is treated as if it did not contain memberd
.Source: C18, §6.7.2.1/20 + /21
I do not understand the explanation of "because struct s
is treated as if it did not contain member d
"
If I use the initializer of { 1, { 4.2 }};
, the { 4.2 }
part is to initialize the flexible array member;
To be precise to initialize the flexible array member to be consisted of one element and initialize this element to the value 4.2
and thus stuct s
is treated as it has member d
or not?
This sentence makes no sense in my eyes.
{ 4.2 }
wouldn't initialize/denote the flexible array member and thus the structure would be treated as if it has no member d
?If I use a fixed size array, this notation works and initializes the member with no complain:
struct foo {
int x;
double y[1];
};
int main (void)
{
struct foo a = { 1, { 2.3 } };
}
Could you elaborate that?
I've read:
Why does static initialization of flexible array member work?
and
How to initialize a structure with flexible array member
and
Flexible array members can lead to undefined behavior?
and others but none of them answers me what this sentence wants to explain and why exactly this this is invalid.
Related:
I guess this is a language defect. While it might make no sense to initialize a flexible array member, the standard needs to address that issue somewhere. I can't find such normative text anywhere.
The definition of a flexible array member is, C17 6.7.2.1/18:
As a special case, the last element of a structure with more than one named member may have an incomplete array type; this is called a flexible array member. In most situations, the flexible array member is ignored. In particular, the size of the structure is as if the flexible array member were omitted except that it may have more trailing padding than the omission would imply.
From this we learn that a flexible array member is an incomplete array type. We do not however learn in what situations the flexible array member is ignored, save for when calculating the size of the struct. "In most situations" isn't helpful and is the defect - this needed to be expanded to an exhaustive list, including the behavior of flexible array members when part of an initializer list. Otherwise one may assume that it behaves just like any other array of incomplete type.
C17 6.2.5/22:
An array type of unknown size is an incomplete type.
And then the rules for initialization say, C17 6.7.9:
The type of the entity to be initialized shall be an array of unknown size or a complete object type that is not a variable length array type.
So far there is no normative text saying that we are not allowed to provide an initializer for a flexible array member - on the contrary. The example in the question (C17 6.7.2.1 example 21) is not normative, since examples aren't normative in ISO standards. The example doesn't mention which constraint that is violated, nor does it mention where it says that the flexible array member must be ignored.
I suppose I'd probably file a DR about this.