Michael Mair said:
S.Tobias said:
Lawrence Kirby <
[email protected]> wrote:
[snippage]
You can't make arrays of structures containing flexible array members
because the size of each element is not known or fixed.
Would you please kindly elaborate on that?
Indeed, FAMs (flexible array members) and VLAs are different. FAMs are
described in 6.7.2.1p16. The size of a struct with a FAM is the
offset of the FAM, therefore such a struct is not an incomplete type.
It is not variably modified type either, because it does not contain a
VLA type (the definition of VM types is in 6.7.5p3).
The last place I looked was in array declarators, and all I found was
in 6.7.5.2p1:
# The element type shall not be an incomplete or function type.
I see nothing that would forbid to create arrays of structs with FAM.
+++
However, I tried this program with Comeau compiler in C99 mode:
[snip code]
[...]
"t.c", line 11: error: type containing an unknown-size array is not allowed
struct flex a[5];
^
It seems to accept a declared object (`f') of type struct flex, but
rejects an array for some reason.
Thank you for answering, however I disagree with your POV.
Because there is no guarantee that the alignment requirements hold
in the sense that there is padding at the end.
But the Standard does not make any requirements for alignment
(it merely allows them); it's up to the implementation fulfill them.
Example: Let sizeof(int)==4, sizeof(short)==2 and the alignment
requirements equal to the size of the type.
Hence,
struct s1 {
int i;
char c;
}
will have a size of 8, but
struct s2 {
int i;
char c;
short s[];
}
has as size of 6 as we assume that
sizeof(structs2)==offsetof(struct s2,s)
Yes, but what's the point? On an architecture without alignment
this shouldn't be a problem, should it?
I think you use your logic in the wrong direction. My reasoning
would be that since the Standard doesn't forbid structs with FAM
being elements of an array, they are allowed. It means that on
an implementation with int alignment 4 bytes, the compiler must
provide padding bits so that sizeof(struct s2) == 8.
and offsetof(struct s2,s)==offsetof(struct s3,s)
with
struct s3 {
int i;
char c;
short s[1];
}
which follows from the (non-normative) example 6.7.2.1#17
No, the Standard is very clear that it does not guarantee this
(footnote 106; and the word "Assuming" in the example).
Note that 6.7.2.1p16 does not provide any recipe for building
struct s2 type; it uses words "an array of unspecified length",
which means it is up to the implementation to decide what length
should be the most suitable.
+++
I think it not wrong to imagine that a FAM is a "member" which
represents the bytes _after_ the body of the struct object
(ie. the FAM does not strictly belong to the struct).
===
For others' convenience, here's the full quote of 6.7.2.1p16:
# 16 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. With two exceptions,
# the flexible array member is ignored. First, the size of the
# structure shall be equal to the offset of the last element of
# an otherwise identical structure that replaces the flexible
# array member with an array of unspecified length.106) Second,
# when a . (or ->) operator has a left operand that is (a pointer
# to) a structure with a flexible array member and the right
# operand names that member, it behaves as if that member were
# replaced with the longest array (with the same element type)
# that would not make the structure larger than the object being
# accessed; the offset of the array shall remain that of the
# flexible array member, even if this would differ from that of
# the replacement array. If this array would have no elements, it
# behaves as if it had one element but the behavior is undefined
# if any attempt is made to access that element or to generate
# a pointer one past it.
#
# 106) The length is unspecified to allow for the fact that
# implementations may give array members different alignments
# according to their lengths.