Path: ...!eternal-september.org!feeder3.eternal-september.org!news.eternal-september.org!eternal-september.org!.POSTED!not-for-mail From: Nick Bowler Newsgroups: comp.lang.c Subject: Re: Regarding assignment to struct Date: Tue, 6 May 2025 19:06:20 -0000 (UTC) Organization: A noiseless patient Spider Lines: 64 Message-ID: References: <86plgo7ahu.fsf@linuxsc.com> <87o6w7h2wn.fsf@nosuchdomain.example.com> <868qnb5gg6.fsf@linuxsc.com> <87bjs6hjpo.fsf@nosuchdomain.example.com> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Injection-Date: Tue, 06 May 2025 21:06:20 +0200 (CEST) Injection-Info: dont-email.me; posting-host="5552b6102635259378647bf32c4c6702"; logging-data="3757870"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1/xyVO+kAu0SeBKiT/98sg0" User-Agent: Pan/0.149 (Bellevue; 4c157ba git@gitlab.gnome.org:GNOME/pan.git) Cancel-Lock: sha1:WKN46C7x/UUdp5PLmAUj3klxDa4= Bytes: 3399 On Mon, 05 May 2025 13:43:31 -0700, Keith Thompson wrote: > Tim Rentsch writes: >> Keith Thompson writes: >>> Andrey Tarasevich writes: >>> [...] >>> >>>> #include >>>> >>>> struct S { int a[10]; }; >>>> >>>> int main() >>>> { >>>> struct S a, b = { 0 }; >>>> int *pa, *pb, *pc; >>>> >>>> pa = &a.a[5]; >>>> pb = &b.a[5]; >>>> pc = &(a = b).a[5]; >>>> >>>> printf("%p %p %p\n", pa, pb, pc); >>>> } >>> >>> [...] >>> >>> I think that code has undefined behavior. >> >> Right. [*] [...] >> [*] Assuming C11 semantics. At best inadvisable under C99 >> semantics, and a constraint violation under C90 semantics. > > What C90 constraint does it violate? Both gcc and clang reject it > with "-std=c90 -pedantic-errors", with an error message "ISO C90 > forbids subscripting non-lvalue array", but I don't see a relevant > constraint in the C90 standard. I don't know about C90, but in C89 the above code violates the constraint on the [] operator that "one of the expressions shall have type ``pointer to object type.''" (3.3.2.1, first paragraph) C89 (3.2.2.1, third paragraph) only describes conversion of lvalues with array type into pointers. No similar rule applies for an expression with array type which is not an lvalue, so such expressions are not converted to pointers. So, given: struct { int a[10]; } a, b; /* ... */ (a = b).a[5]; Since (a = b).a is not an lvalue, it is not converted to a pointer, so neither operand of [] has pointer type, so a diagnostic is required. > I know that C11 introduced "temporary lifetime" to cover cases > like this. In C99, the wording for the indexing operator implicitly > assumes that there's an array object; if there isn't, I'd argue the > behavior is undefined by omission. I'm not aware of any relevant > change from C90 to C99. The rule about conversions from arrays to pointers is different in C99 (n1124 6.3.2.1, third paragraph) compared to C89. In particular, "an lvalue that has type ``array of type'' ..." was changed to "an expression that has type ``array of type'' ...".