Path: csiph.com!eternal-september.org!feeder.eternal-september.org!mx02.eternal-september.org!.POSTED!not-for-mail From: Keith Thompson Newsgroups: comp.lang.c Subject: Re: How does strict aliasing work with parallel arrays in a union or const-initialized data Date: Wed, 28 Oct 2015 18:09:44 -0700 Organization: None to speak of Lines: 117 Message-ID: References: <44332515-f0c2-40f4-b435-c1351188e3bc@googlegroups.com> <6408f9ec-e8d2-4526-96ca-271e1d201484@googlegroups.com> Mime-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit Injection-Info: mx02.eternal-september.org; posting-host="945944de09706c9b4e29b53c9d2efdc2"; logging-data="877"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1/E59v4m7+FaSIDDRS0otUZ" User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/23.1 (gnu/linux) Cancel-Lock: sha1:SwJHPSIjPuimD2k6q1O1hmaXaVo= sha1:7KzU9oy7LbZx9iVZzpTcOvAmK2I= Xref: csiph.com comp.lang.c:74128 Tim Rentsch writes: > Keith Thompson writes: > >> supercat@casperkitty.com writes: >>> On Wednesday, October 28, 2015 at 2:15:29 PM UTC-5, Tim Rentsch wrote: >>>> supercat writes: >>>>>[snip] >>> >>> If I have one translation unit which contains the definitions: >>> >>> struct FOO { int x,y; char b[]; }; >>> struct GOO { int x,y; char b[4]; }; >>> >>> and another that contains those two definitions plus >>> >>> union FOOGOO { FOO f; GOO g; }; [...] >> No. The standard explicitly says that the layouts must be identical in >> the second unit. It makes no such guarantee for the first. > > I believe it does, indirectly. The struct FOO in TU1 and the > struct FOO in TU2 are compatible types, so they must use the same > layout. Similarly for struct GOO's in TU1 and TU2. Therefore > the two struct types in TU1 must use the same layout, because the > corresponding compatible types might have to in another (unknown) > TU that has those corresponding types in a union. Right. I was thinking of the more general case of two distinct struct types with a common initial subsequence. I missed the fact that struct FOO and struct GOO are compatible. > [snip] >>> The coverage of flexible-array members in N1570 seems pretty >>> inadequate; it does not, for example, say that the reported size of a >>> structure with a flexible array member as its last element must be at >>> least equal to the offset of that member within the structure, though >>> I can't see how anyone could be expected to write sane code without >>> such a guarantee. >> >> It doesn't explicitly say it, but it appears to me that that was the >> assumption: >> >> 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. >> >> [snip] > > Note that there was a change in this area between C99 and N1256. > It might be useful to compare this section in the two documents. The change was made in response to Defect Report #282: http://www.open-std.org/jtc1/sc22/wg14/www/docs/dr_282.htm Summary: 6.7.2.1 Structure and union specifiers, paragraphs 15 and 16 require that any padding for alignment of a structure containing a flexible array member must preceed the flexible array member. This contradicts existing implementations. We do not believe this was the intent of the C99 specification. The original wording in C99 was: 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. 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. with a footnote: The length is unspecified to allow for the fact that implementations may give array members different alignments according to their lengths. The revised wording in N1256 was: 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. However, 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. and the footnote was removed. The same wording appears without change in N1570. -- Keith Thompson (The_Other_Keith) kst-u@mib.org Working, but not speaking, for JetHead Development, Inc. "We must do something. This is something. Therefore, we must do this." -- Antony Jay and Jonathan Lynn, "Yes Minister"