Path: csiph.com!eternal-september.org!feeder3.eternal-september.org!news.eternal-september.org!eternal-september.org!.POSTED!not-for-mail From: Tim Rentsch Newsgroups: comp.lang.c Subject: Re: Regarding assignment to struct Date: Mon, 05 May 2025 22:26:22 -0700 Organization: A noiseless patient Spider Lines: 106 Message-ID: <86r0122ttt.fsf@linuxsc.com> References: <86plgo7ahu.fsf@linuxsc.com> <20250505111213.00004b55@yahoo.com> <20250505120145.000014f8@yahoo.com> <20250505202038.000034b9@yahoo.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Injection-Date: Tue, 06 May 2025 07:26:23 +0200 (CEST) Injection-Info: dont-email.me; posting-host="f84420402be78ce51ba0e8f0077f27e2"; logging-data="2337910"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1/JBQHkr5Z2JMUz3V6szW8EaLXY16oP0dA=" User-Agent: Gnus/5.11 (Gnus v5.11) Emacs/22.4 (gnu/linux) Cancel-Lock: sha1:43I/Z6FXPB2Vl/2zV27LukqUq7Y= sha1:wIgsJfcDJfIvDrg+s4sleFPzX7M= Xref: csiph.com comp.lang.c:393198 Michael S writes: > On Mon, 5 May 2025 08:45:09 -0700 > Andrey Tarasevich wrote: > >> On Mon 5/5/2025 2:01 AM, Michael S wrote: >> >>> On Mon, 5 May 2025 01:29:47 -0700 >>> Andrey Tarasevich wrote: >>> >>>> On Mon 5/5/2025 1:12 AM, Michael S wrote: >>>> >>>>> According to my understanding, you are wrong. >>>>> Taking pointer of non-lvalue is UB, so anything compiler does is >>>>> conforming. >>>> >>>> Er... What? What specifically do you mean by "taking pointers"? >>>> >>>> The whole functionality of `[]` operator in C is based on pointers. >>>> This expression >>>> >>>> (a = b).a[5] >>>> [...] >>>> is already doing your "taking pointers of non-lvalue" (if I >>>> understood you correctly) as part of array-to-pointer conversion. >>>> And no, it is not UB. >>>> >>>> This is not UB either >>>> >>>> struct S foo(void) { return (struct S) { 1, 2, 3 }; } >>>> ... >>>> int *p; >>>> p = &foo().a[2], printf("%d\n", *p); >>> >>> That is not UB: >>> int a5 = (a = b).a[5]; >>> >>> That is UB: >>> int* pa5 = &(a = b).a[5]; >> >> No, it isn't. >> >>> If you read the post of Keith Thompson and it is still not clears to >>> you then I can not help. >> >> The only valid "UB" claim in Keith's post is my printing the value of >> `pc` pointer, which by that time happens to point nowhere, since the >> lifetime of the temporary is over. (And, of course, lack of >> conversion to `void *` is an issue). >> >> As for the expressions like >> >> &(a = b).a[5]; >> >> and >> >> &foo().a[2] > > Expressions by themselves a valid. But since there is no situation in > which the value produced by expressions is valid outside of expressions > the compiler can generate any value it wants, even NULL or value > completely outside of address space of current process. These expressions produce valid values as long as they are used before the end of each full expression containing the given expression; within that context they may not produce NULL or a value outside of the program's address space. >> - these by themselves are are perfectly valid. There's no UB in these >> expressions. (And this is not a debate.) >> >> Here's a version of the same code that corrects the above distracting >> issues >> >> #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", (void *) pa, (void *) pb, (void *) pc); >> } >> >> This version has no UB. > > It's only not UB in the nazal demons sense. > It's UB in a sense that we can't predict values of expressions > like (pa==pc) and (pb==pc). I.e. pc is completely useless. In my book > it is form of UB. The term used in the C standard is "unspecified behavior". If this kind of expression is something you don't want to use that is understandable, but it would help communication to use the appropriate standard-defined term to describe it. Essentially all non-trivial programs have unspecified behaviors, and plenty of them. Most are benign, some are problematic, but in no case does an unspecified behavior, by itself, represent a danger to program semantics as severe as executing a construct that has undefined behavior.