Deutsch   English   Français   Italiano  
<864ixz5f43.fsf@linuxsc.com>

View for Bookmarking (what is this?)
Look up another Usenet article

Path: news.eternal-september.org!eternal-september.org!.POSTED!not-for-mail
From: Tim Rentsch <tr.17687@z991.linuxsc.com>
Newsgroups: comp.lang.c
Subject: Re: Regarding assignment to struct
Date: Mon, 05 May 2025 07:03:40 -0700
Organization: A noiseless patient Spider
Lines: 101
Message-ID: <864ixz5f43.fsf@linuxsc.com>
References: <vv338b$16oam$1@dont-email.me> <vv4j9p$33vhj$1@dont-email.me> <86plgo7ahu.fsf@linuxsc.com> <vv9hu7$3nomg$1@dont-email.me> <20250505111213.00004b55@yahoo.com>
MIME-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Injection-Date: Mon, 05 May 2025 16:03:42 +0200 (CEST)
Injection-Info: dont-email.me; posting-host="b2f20e442295d938e3644788cf940be7";
	logging-data="629572"; mail-complaints-to="abuse@eternal-september.org";	posting-account="U2FsdGVkX1+Pmyb/2mRXPEtdfMZwVhcT0+Uhnt7oZwg="
User-Agent: Gnus/5.11 (Gnus v5.11) Emacs/22.4 (gnu/linux)
Cancel-Lock: sha1:e6dPuMu/BTD9e33qMwfSoEf+QhU=
	sha1:vfDR2IPLibfP8lph1Q6s3as2i3M=

Michael S <already5chosen@yahoo.com> writes:

> On Sun, 4 May 2025 22:22:12 -0700
> Andrey Tarasevich <noone@noone.net> wrote:
>
>> On Sun 5/4/2025 6:48 AM, Tim Rentsch wrote:
>>
>>>> One dark corner this feature has, is that in C (as opposed to C++)
>>>> the result of an assignment operator is an rvalue, which can
>>>> easily lead to some interesting consequences related to structs
>>>> with arrays inside.
>>>
>>> I'm curious to know what interesting consequences you mean here.  Do
>>> you mean something other than cases that have undefined behavior?
>>
>> I'm referring to the matter of the address identity of the resultant
>> rvalue object.  At first, "address identity of rvalue" might sound
>> strange, but the standard says that there's indeed an object tied to
>> such rvalue, and once we start applying array-to-pointer conversion
>> (and use `[]` operator), lvalues and addresses quickly come into the
>> picture.
>>
>> The standard says in 6.2.4/8:
>>
>> "A non-lvalue expression with structure or union type, where the
>> structure or union contains a member with array type [...]
>> refers to an object with automatic storage duration and temporary
>> lifetime.  Its lifetime begins when the expression is evaluated and
>> its initial value is the value of the expression.  Its lifetime ends
>> when the evaluation of the containing full expression ends.  [...]
>> Such an object need not have a unique address."
>> https://port70.net/~nsz/c/c11/n1570.html#6.2.4p8
>>
>> I wondering what the last sentence is intended to mean ("... need not
>> have a unique address").  At the first sight, the intent seems to be
>> obvious:  it simply says that such temporary objects might repeatedly
>> appear (and disappear) at the same location in storage, which is a
>> natural thing to expect.
>>
>> But is it, perhaps, intended to also allow such temporaries to have
>> addresses identical to regular named objects?  It is not immediately
>> clear to me.
>>
>> And when I make the following experiment with GCC and Clang
>>
>>    #include <stdio.h>
>>
>>    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 consistently get the following output from GCC
>>
>>    0x7fff73eb5544 0x7fff73eb5574 0x7fff73eb5544
>>
>> And this is what I get from Clang
>>
>>    0x7ffd2b8dbf44 0x7ffd2b8dbf14 0x7ffd2b8dbee4
>>
>> As you can see, GCC apparently took C++-like approach to this
>> situation.  The returned "temporary" is not really a separate
>> temporary at all, but actually `a` itself.
>>
>> Meanwhile, in Clang all three pointers are different, i.e. Clang
>> decided to actually create a separate temporary object for the result
>> of the assignment.
>>
>> I have a strong feeling that GCC's behavior is non-conforming.  The
>> last sentence of 6.2.4/8 is not supposed to permit "projecting" the
>> resultant temporaries onto existing named objects.  I could be wrong...
>
> According to my understanding, you are wrong.
> Taking pointer of non-lvalue is UB, so anything compiler does is
> conforming.

Maybe you are thinking of C90.

In both C99 and C11, the expression

   (a = b).a[5]

is an lvalue, so taking its address with & is allowed.

It's easy to verify this assertion using gcc -std=c99 -pedantic.  If
the given expression were not an lvalue then taking its address with
& would be a constraint violation, requiring a diagnostic.  But no
diagnostic is produced.  (Using clang in place of gcc also produces
no diagnostic.)

The behavior under C99 semantics is arguably murky.  But under C11
semantics the behavior is well-defined.