Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.c > #393106 > unrolled thread

Regarding assignment to struct

Started byLew Pitcher <lew.pitcher@digitalfreehold.ca>
First post2025-05-02 18:34 +0000
Last post2025-05-04 14:09 -0700
Articles 20 on this page of 109 — 20 participants

Back to article view | Back to comp.lang.c


Contents

  Regarding assignment to struct Lew Pitcher <lew.pitcher@digitalfreehold.ca> - 2025-05-02 18:34 +0000
    Re: Regarding assignment to struct Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2025-05-02 13:17 -0700
    Re: Regarding assignment to struct Barry Schwarz <schwarzb@delq.com> - 2025-05-02 13:35 -0700
      That depends... (Was: Regarding assignment to struct) gazelle@shell.xmission.com (Kenny McCormack) - 2025-05-02 20:44 +0000
        Re: That depends... (Was: Regarding assignment to struct) Lew Pitcher <lew.pitcher@digitalfreehold.ca> - 2025-05-03 01:13 +0000
          Re: That depends... (Was: Regarding assignment to struct) Lawrence D'Oliveiro <ldo@nz.invalid> - 2025-05-03 02:28 +0000
          Re: That depends... (Was: Regarding assignment to struct) Janis Papanagnou <janis_papanagnou+ng@hotmail.com> - 2025-05-03 06:17 +0200
          Re: That depends... (Was: Regarding assignment to struct) Kaz Kylheku <643-408-1753@kylheku.com> - 2025-05-03 04:31 +0000
            Re: That depends... (Was: Regarding assignment to struct) Kaz Kylheku <643-408-1753@kylheku.com> - 2025-05-03 05:11 +0000
              Re: That depends... (Was: Regarding assignment to struct) Janis Papanagnou <janis_papanagnou+ng@hotmail.com> - 2025-05-05 12:30 +0200
                Re: That depends... (Was: Regarding assignment to struct) Kaz Kylheku <643-408-1753@kylheku.com> - 2025-05-05 18:47 +0000
            Re: That depends... (Was: Regarding assignment to struct) Tim Rentsch <tr.17687@z991.linuxsc.com> - 2025-05-04 11:05 -0700
          Re: That depends... (Was: Regarding assignment to struct) James Kuyper <jameskuyper@alumni.caltech.edu> - 2025-05-03 00:47 -0400
          Re: That depends... (Was: Regarding assignment to struct) Tim Rentsch <tr.17687@z991.linuxsc.com> - 2025-05-04 10:59 -0700
            Re: That depends... (Was: Regarding assignment to struct) Lew Pitcher <lew.pitcher@digitalfreehold.ca> - 2025-05-04 18:16 +0000
    Re: Regarding assignment to struct antispam@fricas.org (Waldek Hebisch) - 2025-05-02 21:35 +0000
      Re: Regarding assignment to struct Lew Pitcher <lew.pitcher@digitalfreehold.ca> - 2025-05-03 01:43 +0000
    Re: Regarding assignment to struct Andrey Tarasevich <noone@noone.net> - 2025-05-03 01:14 -0700
      Re: Regarding assignment to struct Lawrence D'Oliveiro <ldo@nz.invalid> - 2025-05-03 22:46 +0000
        Re: Regarding assignment to struct Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2025-05-03 17:37 -0700
          Re: Regarding assignment to struct James Kuyper <jameskuyper@alumni.caltech.edu> - 2025-05-03 23:38 -0400
            Re: Regarding assignment to struct gazelle@shell.xmission.com (Kenny McCormack) - 2025-05-04 09:25 +0000
            Re: Regarding assignment to struct scott@slp53.sl.home (Scott Lurndal) - 2025-05-04 14:27 +0000
              Re: Regarding assignment to struct David Brown <david.brown@hesbynett.no> - 2025-05-04 18:45 +0200
            Re: Regarding assignment to struct Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2025-05-04 13:20 -0700
              Re: Regarding assignment to struct scott@slp53.sl.home (Scott Lurndal) - 2025-05-05 00:41 +0000
                Re: Regarding assignment to struct Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2025-05-04 18:42 -0700
                Re: Regarding assignment to struct Tim Rentsch <tr.17687@z991.linuxsc.com> - 2025-05-05 21:57 -0700
              Re: Regarding assignment to struct James Kuyper <jameskuyper@alumni.caltech.edu> - 2025-05-04 21:08 -0400
      Re: Regarding assignment to struct Lawrence D'Oliveiro <ldo@nz.invalid> - 2025-05-03 22:47 +0000
      Re: Regarding assignment to struct Lawrence D'Oliveiro <ldo@nz.invalid> - 2025-05-03 22:46 +0000
      Re: Regarding assignment to struct Tim Rentsch <tr.17687@z991.linuxsc.com> - 2025-05-04 06:48 -0700
        Re: Regarding assignment to struct Andrey Tarasevich <noone@noone.net> - 2025-05-04 22:22 -0700
          Re: Regarding assignment to struct Michael S <already5chosen@yahoo.com> - 2025-05-05 11:12 +0300
            Re: Regarding assignment to struct Andrey Tarasevich <noone@noone.net> - 2025-05-05 01:29 -0700
              Re: Regarding assignment to struct Michael S <already5chosen@yahoo.com> - 2025-05-05 12:01 +0300
                Re: Regarding assignment to struct Tim Rentsch <tr.17687@z991.linuxsc.com> - 2025-05-05 07:14 -0700
                Re: Regarding assignment to struct Andrey Tarasevich <noone@noone.net> - 2025-05-05 08:45 -0700
                  Re: Regarding assignment to struct Michael S <already5chosen@yahoo.com> - 2025-05-05 20:20 +0300
                    Re: Regarding assignment to struct Tim Rentsch <tr.17687@z991.linuxsc.com> - 2025-05-05 22:26 -0700
                    Re: Regarding assignment to struct Andrey Tarasevich <noone@noone.net> - 2025-05-29 05:11 -0700
                    Re: Regarding assignment to struct James Kuyper <jameskuyper@alumni.caltech.edu> - 2025-05-29 12:57 -0400
                  Re: Regarding assignment to struct Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2025-05-05 13:27 -0700
                    Re: Regarding assignment to struct Tim Rentsch <tr.17687@z991.linuxsc.com> - 2025-05-05 17:04 -0700
                      Re: Regarding assignment to struct Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2025-05-05 17:53 -0700
                        Re: Regarding assignment to struct Tim Rentsch <tr.17687@z991.linuxsc.com> - 2026-03-01 18:54 -0800
                          Re: Regarding assignment to struct Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2026-03-01 19:36 -0800
                    Re: Regarding assignment to struct David Brown <david.brown@hesbynett.no> - 2025-05-06 11:35 +0200
                      Re: Regarding assignment to struct Andrey Tarasevich <noone@noone.net> - 2025-05-29 05:19 -0700
                        Re: Regarding assignment to struct David Brown <david.brown@hesbynett.no> - 2025-05-29 21:05 +0200
                    Re: Regarding assignment to struct antispam@fricas.org (Waldek Hebisch) - 2025-05-06 17:36 +0000
                      Re: Regarding assignment to struct David Brown <david.brown@hesbynett.no> - 2025-05-06 20:46 +0200
                        Re: Regarding assignment to struct scott@slp53.sl.home (Scott Lurndal) - 2025-05-06 19:22 +0000
                          Re: Regarding assignment to struct David Brown <david.brown@hesbynett.no> - 2025-05-07 09:37 +0200
                            Re: Regarding assignment to struct Andrey Tarasevich <noone@noone.net> - 2025-05-29 05:49 -0700
                              Re: Regarding assignment to struct Janis Papanagnou <janis_papanagnou+ng@hotmail.com> - 2025-05-29 16:33 +0200
                              Re: Regarding assignment to struct David Brown <david.brown@hesbynett.no> - 2025-05-29 21:20 +0200
                                Re: Regarding assignment to struct scott@slp53.sl.home (Scott Lurndal) - 2025-05-29 21:15 +0000
                                  Re: Regarding assignment to struct Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2025-05-29 14:54 -0700
                                    Re: Regarding assignment to struct scott@slp53.sl.home (Scott Lurndal) - 2025-05-30 14:29 +0000
                                  Re: Regarding assignment to struct David Brown <david.brown@hesbynett.no> - 2025-05-30 10:50 +0200
                              Re: Regarding assignment to struct Tim Rentsch <tr.17687@z991.linuxsc.com> - 2025-12-22 04:40 -0800
                      Re: Regarding assignment to struct Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2025-05-06 13:06 -0700
                      Re: Regarding assignment to struct Andrey Tarasevich <noone@noone.net> - 2025-05-29 05:21 -0700
                        Re: Regarding assignment to struct Janis Papanagnou <janis_papanagnou+ng@hotmail.com> - 2025-05-29 16:43 +0200
                        Re: Regarding assignment to struct Tim Rentsch <tr.17687@z991.linuxsc.com> - 2025-06-06 17:44 -0700
                    Re: Regarding assignment to struct Andrey Tarasevich <noone@noone.net> - 2025-05-29 05:14 -0700
                      Re: Regarding assignment to struct Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2025-05-29 13:56 -0700
            Re: Regarding assignment to struct Tim Rentsch <tr.17687@z991.linuxsc.com> - 2025-05-05 07:03 -0700
          Re: Regarding assignment to struct Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2025-05-05 01:26 -0700
            Re: Regarding assignment to struct Andrey Tarasevich <noone@noone.net> - 2025-05-05 10:14 -0700
              Re: Regarding assignment to struct Tim Rentsch <tr.17687@z991.linuxsc.com> - 2025-05-08 12:45 -0700
                Re: Regarding assignment to struct David Brown <david.brown@hesbynett.no> - 2025-05-08 22:20 +0200
          Re: Regarding assignment to struct Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2025-05-05 01:34 -0700
            Re: Regarding assignment to struct Michael S <already5chosen@yahoo.com> - 2025-05-05 12:03 +0300
              Re: Regarding assignment to struct gazelle@shell.xmission.com (Kenny McCormack) - 2025-05-05 11:30 +0000
              Re: Regarding assignment to struct Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2025-05-05 13:32 -0700
                Re: Regarding assignment to struct Kaz Kylheku <643-408-1753@kylheku.com> - 2025-05-05 21:10 +0000
                  Re: Regarding assignment to struct Tim Rentsch <tr.17687@z991.linuxsc.com> - 2025-05-05 22:57 -0700
              Re: Regarding assignment to struct Tim Rentsch <tr.17687@z991.linuxsc.com> - 2025-05-05 22:40 -0700
            Re: Regarding assignment to struct Tim Rentsch <tr.17687@z991.linuxsc.com> - 2025-05-05 06:34 -0700
              Re: Regarding assignment to struct Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2025-05-05 13:43 -0700
                Re: Regarding assignment to struct Nick Bowler <nbowler@draconx.ca> - 2025-05-06 19:06 +0000
                  Re: Regarding assignment to struct Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2025-05-06 13:21 -0700
                    Re: Regarding assignment to struct Nick Bowler <nbowler@draconx.ca> - 2025-05-07 19:09 +0000
                      Re: Regarding assignment to struct Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2025-05-07 14:23 -0700
                        Re: Regarding assignment to struct Nick Bowler <nbowler@draconx.ca> - 2025-05-08 12:58 +0000
                      Re: Regarding assignment to struct Tim Rentsch <tr.17687@z991.linuxsc.com> - 2025-05-07 21:17 -0700
                Re: Regarding assignment to struct Andrey Tarasevich <noone@noone.net> - 2025-05-29 05:36 -0700
                  Re: Regarding assignment to struct Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2025-05-29 14:36 -0700
          Re: Regarding assignment to struct Tim Rentsch <tr.17687@z991.linuxsc.com> - 2025-05-05 07:56 -0700
            Re: Regarding assignment to struct David Brown <david.brown@hesbynett.no> - 2025-05-05 20:00 +0200
          Re: Regarding assignment to struct NotAorB <atod101101@gmail.com> - 2025-05-12 16:38 -0400
    Re: Regarding assignment to struct David Brown <david.brown@hesbynett.no> - 2025-05-03 11:46 +0200
      Re: Regarding assignment to struct Muttley@dastardlyhq.com - 2025-05-05 08:50 +0000
        Re: Regarding assignment to struct David Brown <david.brown@hesbynett.no> - 2025-05-05 13:34 +0200
        Re: Regarding assignment to struct Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2025-05-05 13:53 -0700
          Re: Regarding assignment to struct Muttley@DastardlyHQ.org - 2025-05-06 07:16 +0000
          Re: Regarding assignment to struct David Brown <david.brown@hesbynett.no> - 2025-05-06 11:46 +0200
            Re: Regarding assignment to struct Muttley@DastardlyHQ.org - 2025-05-06 10:18 +0000
          Re: Regarding assignment to struct Michael S <already5chosen@yahoo.com> - 2025-05-06 16:34 +0300
    Re: Regarding assignment to struct Richard Damon <richard@damon-family.org> - 2025-05-03 21:42 -0400
      Re: Regarding assignment to struct Michael S <already5chosen@yahoo.com> - 2025-05-04 11:01 +0300
        Re: Regarding assignment to struct Lawrence D'Oliveiro <ldo@nz.invalid> - 2025-05-04 08:34 +0000
          Re: Regarding assignment to struct David Brown <david.brown@hesbynett.no> - 2025-05-04 14:06 +0200
        Re: Regarding assignment to struct Tim Rentsch <tr.17687@z991.linuxsc.com> - 2025-05-05 21:25 -0700
        Re: Regarding assignment to struct Rosario19 <Ros@invalid.invalid> - 2025-05-12 11:23 +0200
    Re: Regarding assignment to struct Tim Rentsch <tr.17687@z991.linuxsc.com> - 2025-05-04 07:49 -0700
    Re: Regarding assignment to struct Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2025-05-04 14:09 -0700

Page 2 of 6 — ← Prev page 1 [2] 3 4 5 6  Next page →


#393128

FromJames Kuyper <jameskuyper@alumni.caltech.edu>
Date2025-05-03 23:38 -0400
Message-ID<vv6ng8$1410m$1@dont-email.me>
In reply to#393125
On 5/3/25 20:37, Keith Thompson wrote:
> Lawrence D'Oliveiro <ldo@nz.invalid> writes:
>> On Sat, 3 May 2025 01:14:46 -0700, Andrey Tarasevich wrote:
>>> Virtually every C project relies on assignment of structures.
>>> Passing-returning structs by value might be more rare (although
>>> perfectly valid and often appropriate too), but assignment...
>>> assignment is used by everyone everywhere without even giving it a
>>> second thought.
>>
>> There is a caveat, to do with alignment padding: will this always have a 
>> defined value?
> 
> I don't believe so.  In a quick look, I don't see anything in
> the standard that explicitly addresses this, but I believe that a
> conforming implementation could implement structure assignment by
> copying the individual members, leaving any padding in the target
> undefined.

"When a value is stored in an object of structure or union type,
including in a member object, the bytes of the object representation
that correspond to any padding bytes take unspecified values.56)"
(6.2.6.1p6).

That refers to footnote 56, which says "Thus, for example, structure
assignment need not copy any padding bits."

Note that, even when writing to a single member, the representations in
the padding bytes might be affected. A plausible reason for this to
happen would be, for example when a value is written to an 8-bit strujct
field followed by 8 bits of padding on a machine where the word size is
16 bits. The wording of that clause permits the use of instructions that
change the contents of an entire word to be used when updating that field.

> Finally, why would you care?

The fact that an implementation does not have to do the equivalent of
memcpy() to perform a struct copy means that successful assignment
cannot be checked by using memcmp().

[toc] | [prev] | [next] | [standalone]


#393131

Fromgazelle@shell.xmission.com (Kenny McCormack)
Date2025-05-04 09:25 +0000
Message-ID<vv7bpk$2n9mf$1@news.xmission.com>
In reply to#393128
In article <vv6ng8$1410m$1@dont-email.me>,
James Kuyper  <jameskuyper@alumni.caltech.edu> wrote:
...
>The fact that an implementation does not have to do the equivalent of
>memcpy() to perform a struct copy means that successful assignment
>cannot be checked by using memcmp().

Which then begs two questions:

    1) Why wouldn't an implementaton do it with memcpy()?  That is likely
    to be as good or better than any other method, including, especially, a
    member-by-member copy.

    2) Why wouldn't you, the programmer, just use memcpy() instead of
    struct assignment?  Yes, I realize there are other cases to consider,
    but in the simple one:

    	struct something foo,bar;
	foo = bar;

    memcpy() seems like it would always be easier and more reliable.

-- 
The randomly chosen signature file that would have appeared here is more than 4
lines long.  As such, it violates one or more Usenet RFCs.  In order to remain
in compliance with said RFCs, the actual sig can be found at the following URL:
	http://user.xmission.com/~gazelle/Sigs/Pedantic

[toc] | [prev] | [next] | [standalone]


#393136

Fromscott@slp53.sl.home (Scott Lurndal)
Date2025-05-04 14:27 +0000
Message-ID<VOKRP.167848$7IN2.2401@fx15.iad>
In reply to#393128
James Kuyper <jameskuyper@alumni.caltech.edu> writes:
>On 5/3/25 20:37, Keith Thompson wrote:
>> Lawrence D'Oliveiro <ldo@nz.invalid> writes:
>>> On Sat, 3 May 2025 01:14:46 -0700, Andrey Tarasevich wrote:
>>>> Virtually every C project relies on assignment of structures.
>>>> Passing-returning structs by value might be more rare (although
>>>> perfectly valid and often appropriate too), but assignment...
>>>> assignment is used by everyone everywhere without even giving it a
>>>> second thought.
>>>
>>> There is a caveat, to do with alignment padding: will this always have a 
>>> defined value?
>> 
>> I don't believe so.  In a quick look, I don't see anything in
>> the standard that explicitly addresses this, but I believe that a
>> conforming implementation could implement structure assignment by
>> copying the individual members, leaving any padding in the target
>> undefined.
>
>"When a value is stored in an object of structure or union type,
>including in a member object, the bytes of the object representation
>that correspond to any padding bytes take unspecified values.56)"
>(6.2.6.1p6).
>
>That refers to footnote 56, which says "Thus, for example, structure
>assignment need not copy any padding bits."

Are there any C implementations in common use that don't just
use memcpy or an optimized version thereof?

[toc] | [prev] | [next] | [standalone]


#393144

FromDavid Brown <david.brown@hesbynett.no>
Date2025-05-04 18:45 +0200
Message-ID<vv85jc$2c9b3$2@dont-email.me>
In reply to#393136
On 04/05/2025 16:27, Scott Lurndal wrote:
> James Kuyper <jameskuyper@alumni.caltech.edu> writes:
>> On 5/3/25 20:37, Keith Thompson wrote:
>>> Lawrence D'Oliveiro <ldo@nz.invalid> writes:
>>>> On Sat, 3 May 2025 01:14:46 -0700, Andrey Tarasevich wrote:
>>>>> Virtually every C project relies on assignment of structures.
>>>>> Passing-returning structs by value might be more rare (although
>>>>> perfectly valid and often appropriate too), but assignment...
>>>>> assignment is used by everyone everywhere without even giving it a
>>>>> second thought.
>>>>
>>>> There is a caveat, to do with alignment padding: will this always have a
>>>> defined value?
>>>
>>> I don't believe so.  In a quick look, I don't see anything in
>>> the standard that explicitly addresses this, but I believe that a
>>> conforming implementation could implement structure assignment by
>>> copying the individual members, leaving any padding in the target
>>> undefined.
>>
>> "When a value is stored in an object of structure or union type,
>> including in a member object, the bytes of the object representation
>> that correspond to any padding bytes take unspecified values.56)"
>> (6.2.6.1p6).
>>
>> That refers to footnote 56, which says "Thus, for example, structure
>> assignment need not copy any padding bits."
> 
> Are there any C implementations in common use that don't just
> use memcpy or an optimized version thereof?
> 

Sometimes small structs never make it to memory, or are handled by the 
compiler as though they were individual variables (as long as that is 
within "as-if" usage, of course).  Copying a struct might merely mean 
the compiler keeps track of the logical copy without actually copying 
any memory.  (You could argue that the compiler is still treating it 
like memcpy, as memcpy calls don't always copy something.)

I think it would be unusual to see a significant difference between a 
struct assignment copy and a memcpy on a compiler that optimises memcpy 
well.

But on a compiler that does not handle memcpy well, then a struct 
assignment could be inlined while a memcpy could mean an external 
library call with significant overhead.

[toc] | [prev] | [next] | [standalone]


#393149

FromKeith Thompson <Keith.S.Thompson+u@gmail.com>
Date2025-05-04 13:20 -0700
Message-ID<87bjs8p1qd.fsf@nosuchdomain.example.com>
In reply to#393128
James Kuyper <jameskuyper@alumni.caltech.edu> writes:
> On 5/3/25 20:37, Keith Thompson wrote:
>> Lawrence D'Oliveiro <ldo@nz.invalid> writes:
>>> On Sat, 3 May 2025 01:14:46 -0700, Andrey Tarasevich wrote:
>>>> Virtually every C project relies on assignment of structures.
>>>> Passing-returning structs by value might be more rare (although
>>>> perfectly valid and often appropriate too), but assignment...
>>>> assignment is used by everyone everywhere without even giving it a
>>>> second thought.
>>>
>>> There is a caveat, to do with alignment padding: will this always have a 
>>> defined value?
>> 
>> I don't believe so.  In a quick look, I don't see anything in
>> the standard that explicitly addresses this, but I believe that a
>> conforming implementation could implement structure assignment by
>> copying the individual members, leaving any padding in the target
>> undefined.
>
> "When a value is stored in an object of structure or union type,
> including in a member object, the bytes of the object representation
> that correspond to any padding bytes take unspecified values.56)"
> (6.2.6.1p6).
>
> That refers to footnote 56, which says "Thus, for example, structure
> assignment need not copy any padding bits."

Yes, that's what I missed.

It's interesting that the footnote refers to padding *bits* rather than
padding *bytes*.  I presume this was unintentional.

Padding bytes are bytes within a structure or union that are not part of
any member.  Padding *bits* are bits within the representation of an
integer type that do not convert to an object's value.  I believe it's
true that integer padding bits need not be copied by assignment (for
example, they might be normalized to 0 for some reason), but that's
not specific to struct or union assignment.

There can also be bits within a struct or union representation that are
adjacent to a bit-field and do not contribute to any value.  As far as I
know, there's no name for those bits.

[snip]

>> Finally, why would you care?
>
> The fact that an implementation does not have to do the equivalent of
> memcpy() to perform a struct copy means that successful assignment
> cannot be checked by using memcmp().

Are you referring to checking whether an assignment was performed
or not, due to uncertainty about what the program has done?  If you
mean doing an assignment and then checking whether it succeeded,
I can't think of a context where that makes sense.

-- 
Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
void Void(void) { Void(); } /* The recursive call of the void */

[toc] | [prev] | [next] | [standalone]


#393152

Fromscott@slp53.sl.home (Scott Lurndal)
Date2025-05-05 00:41 +0000
Message-ID<zOTRP.133506$U3L2.93512@fx16.iad>
In reply to#393149
Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:
>James Kuyper <jameskuyper@alumni.caltech.edu> writes:
>> On 5/3/25 20:37, Keith Thompson wrote:
>>> Lawrence D'Oliveiro <ldo@nz.invalid> writes:
>>>> On Sat, 3 May 2025 01:14:46 -0700, Andrey Tarasevich wrote:
>>>>> Virtually every C project relies on assignment of structures.
>>>>> Passing-returning structs by value might be more rare (although
>>>>> perfectly valid and often appropriate too), but assignment...
>>>>> assignment is used by everyone everywhere without even giving it a
>>>>> second thought.
>>>>
>>>> There is a caveat, to do with alignment padding: will this always have a 
>>>> defined value?
>>> 
>>> I don't believe so.  In a quick look, I don't see anything in
>>> the standard that explicitly addresses this, but I believe that a
>>> conforming implementation could implement structure assignment by
>>> copying the individual members, leaving any padding in the target
>>> undefined.
>>
>> "When a value is stored in an object of structure or union type,
>> including in a member object, the bytes of the object representation
>> that correspond to any padding bytes take unspecified values.56)"
>> (6.2.6.1p6).
>>
>> That refers to footnote 56, which says "Thus, for example, structure
>> assignment need not copy any padding bits."
>
>Yes, that's what I missed.
>
>It's interesting that the footnote refers to padding *bits* rather than
>padding *bytes*.  I presume this was unintentional.

Padding bits:

        struct A {
            uint64_t    tlen  : 16,
                              : 20,
                        pkind :  6,
                        fsz   :  6,
                        gsz   : 14,
                        g     :  1,
                        ptp   :  1;
        } s;

There are 20 padding bits in this declaration.  Perhaps that's
what they're referring to?

[toc] | [prev] | [next] | [standalone]


#393154

FromKeith Thompson <Keith.S.Thompson+u@gmail.com>
Date2025-05-04 18:42 -0700
Message-ID<87y0vbomt1.fsf@nosuchdomain.example.com>
In reply to#393152
scott@slp53.sl.home (Scott Lurndal) writes:
> Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:
>>James Kuyper <jameskuyper@alumni.caltech.edu> writes:
>>> On 5/3/25 20:37, Keith Thompson wrote:
>>>> Lawrence D'Oliveiro <ldo@nz.invalid> writes:
>>>>> On Sat, 3 May 2025 01:14:46 -0700, Andrey Tarasevich wrote:
>>>>>> Virtually every C project relies on assignment of structures.
>>>>>> Passing-returning structs by value might be more rare (although
>>>>>> perfectly valid and often appropriate too), but assignment...
>>>>>> assignment is used by everyone everywhere without even giving it a
>>>>>> second thought.
>>>>>
>>>>> There is a caveat, to do with alignment padding: will this always have a 
>>>>> defined value?
>>>> 
>>>> I don't believe so.  In a quick look, I don't see anything in
>>>> the standard that explicitly addresses this, but I believe that a
>>>> conforming implementation could implement structure assignment by
>>>> copying the individual members, leaving any padding in the target
>>>> undefined.
>>>
>>> "When a value is stored in an object of structure or union type,
>>> including in a member object, the bytes of the object representation
>>> that correspond to any padding bytes take unspecified values.56)"
>>> (6.2.6.1p6).
>>>
>>> That refers to footnote 56, which says "Thus, for example, structure
>>> assignment need not copy any padding bits."
>>
>>Yes, that's what I missed.
>>
>>It's interesting that the footnote refers to padding *bits* rather than
>>padding *bytes*.  I presume this was unintentional.
>
> Padding bits:
>
>         struct A {
>             uint64_t    tlen  : 16,
>                               : 20,
>                         pkind :  6,
>                         fsz   :  6,
>                         gsz   : 14,
>                         g     :  1,
>                         ptp   :  1;
>         } s;
>
> There are 20 padding bits in this declaration.  Perhaps that's
> what they're referring to?

I don't believe so, at least not entirely.  For one thing the terms
"padding bits" is used only to refer to bits in the representation
of an integer object that do not contribute to the object's value,
and "padding bytes" is used only to refer to unused bytes within
a struct or union.  (Neither term is in italics, so there is no
formal definition for either, but the standard's usage is consistent.)

The standard does use the word "padding" in reference to unnamed
bit-fields, but not "padding bits".

(Pointer and floating-point objects may have bits that don't
contribute to their values, but the standard doesn't say enough
about their representations for the concept of padding bits to
be necessary.)

Furthermore the sentence to which the footnote is attached says:

    When a value is stored in an object of structure or union type,
    including in a member object, the bytes of the object representation
    that correspond to any padding bytes take unspecified values.

and the footnote says:

    Thus, for example, structure assignment need not copy any padding
    bits.

The switch from "padding bytes" to "padding bits" seems odd.
Of course bytes are made of bits, so it's not unreasonable to say
that padding bytes are made of padding bits, particularly since
neither term has a formal definition.

I've tracked the current wording of the footnote to DR #222,
<https://www.open-std.org/jtc1/sc22/wg14/www/docs/dr_222.htm>, applied
in Technical Corrigendum 2 after C99.  In the C99 standard, the footnote
says:

    Thus, for example, structure assignment may be implemented
    element-at-a-time or via memcpy.

DR 222 established that structs and unions do not have trap
representations.  Element-at-a-time copying could cause undefined
behavior if a member has a trap representation ("non-value
representation" in C23).  The revised footnote is a more general
statement about padding.

There are four kinds of "padding" that might appear within a struct
(that I can think of):

- Bytes between members or after the last one, typically used to satisfy
  alignment requirements (the standard calls these "padding bytes");
- Bits between or after bit-fields or in anonymous bit-fields;
- Bits within an integer (sub)member that do not contribute to its
  value (the standard calls these "padding bits"); and
- Bits within a pointer or floating-point (sub)member that do not
  contribute to its value.  The standard doesn't talk about these much,
  but for example a pointer or floating-point assignment might result in
  a normalized representation in the target that differs from the
  representation of the source.

It's plausible that the term "padding bits" in the footnote is
intended to cover all of these.

When I started looking into this, I assumed that "padding bits"
was a defined term.  If it were, then using it to refer to
anything other than bits within an integer object representation,
would be incorrect.  Since it isn't, using the term "padding bits"
more generally is perhaps slightly confusing, but not necessarily
a problem.

-- 
Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
void Void(void) { Void(); } /* The recursive call of the void */

[toc] | [prev] | [next] | [standalone]


#393197

FromTim Rentsch <tr.17687@z991.linuxsc.com>
Date2025-05-05 21:57 -0700
Message-ID<86v7qe2v5g.fsf@linuxsc.com>
In reply to#393152
scott@slp53.sl.home (Scott Lurndal) writes:

> Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:
>
>> James Kuyper <jameskuyper@alumni.caltech.edu> writes:
>>
>>> On 5/3/25 20:37, Keith Thompson wrote:
>>>
>>>> Lawrence D'Oliveiro <ldo@nz.invalid> writes:
>>>>
>>>>> On Sat, 3 May 2025 01:14:46 -0700, Andrey Tarasevich wrote:
>>>>>
>>>>>> Virtually every C project relies on assignment of structures.
>>>>>> Passing-returning structs by value might be more rare (although
>>>>>> perfectly valid and often appropriate too), but assignment...
>>>>>> assignment is used by everyone everywhere without even giving
>>>>>> it a second thought.
>>>>>
>>>>> There is a caveat, to do with alignment padding:  will this
>>>>> always have a defined value?
>>>>
>>>> I don't believe so.  In a quick look, I don't see anything in
>>>> the standard that explicitly addresses this, but I believe that a
>>>> conforming implementation could implement structure assignment by
>>>> copying the individual members, leaving any padding in the target
>>>> undefined.
>>>
>>> "When a value is stored in an object of structure or union type,
>>> including in a member object, the bytes of the object
>>> representation that correspond to any padding bytes take
>>> unspecified values.56)" (6.2.6.1p6).
>>>
>>> That refers to footnote 56, which says "Thus, for example,
>>> structure assignment need not copy any padding bits."
>>
>> Yes, that's what I missed.
>>
>> It's interesting that the footnote refers to padding *bits* rather
>> than padding *bytes*.  I presume this was unintentional.
>
> Padding bits:
>
>         struct A {
>             uint64_t    tlen  : 16,
>                               : 20,
>                         pkind :  6,
>                         fsz   :  6,
>                         gsz   : 14,
>                         g     :  1,
>                         ptp   :  1;
>         } s;
>
> There are 20 padding bits in this declaration.  Perhaps that's
> what they're referring to?

To me it seems clear that the "padding bits" here is meant to refer
to all of the following:

   unoccupied bytes between members, due to member alignment
   unoccupied bytes at the end of a structure or union
   bits corresponding to unnamed bit-field members
   unoccupied bits or bytes caused by explicit bit-field alignment
   unoccupied bits or bytes caused by other bit-field alignment

Any member objects may have their own internal padding bits.  Any
assignment of a struct or union follows the usual rule that any
padding bits that are part of a target member have unspecified
values (as long as the member doesn't become a trap representation
as a result).

Considering all these parts together, I think it makes sense to say
that the padding bits of an object are those bits that do not
participate in determining the abstract value of the object (not
counting that some combination of padding bits might cause the
object to become a trap representation, which never happens for
structs or unions).

(Yes I know that the term "trap representation" has been changed in
later versions of the C standard.  Please make any needed editorial
changes internally, without having to post a followup.)

[toc] | [prev] | [next] | [standalone]


#393153

FromJames Kuyper <jameskuyper@alumni.caltech.edu>
Date2025-05-04 21:08 -0400
Message-ID<vv932r$37tbq$1@dont-email.me>
In reply to#393149
On 5/4/25 16:20, Keith Thompson wrote:
> James Kuyper <jameskuyper@alumni.caltech.edu> writes:
>> On 5/3/25 20:37, Keith Thompson wrote:
...
>>> I don't believe so. In a quick look, I don't see anything in
>>> the standard that explicitly addresses this, but I believe that a
>>> conforming implementation could implement structure assignment by
>>> copying the individual members, leaving any padding in the target
>>> undefined.
...
>>> Finally, why would you care?
>>
>> The fact that an implementation does not have to do the equivalent of
>> memcpy() to perform a struct copy means that successful assignment
>> cannot be checked by using memcmp().
>
> Are you referring to checking whether an assignment was performed
> or not, due to uncertainty about what the program has done? If you
> mean doing an assignment and then checking whether it succeeded,
> I can't think of a context where that makes sense.

Sorry, I didn't explain what I was thinking about in any detail. I've
seen code that allows a data structure to be modified by one section of
the code, and then periodically checks each object in that data
structure (including aggregate objects) to see whether it has been
modified by using memcmp() versus a saved copy. If so, it updated the
saved copy, including a timestamp when it was updated. If it weren't for
the need to keep track of the timestamp, it would always be simpler, and
not much slower, to always replace the saved copy, whether or not
there'd been a change.

I should have made it clear that I basically understand and agree with
your "why would you care" criticism. But it's part of my nature to look
for the edge cases where differences that ordinarily don't matter, could
matter.

[toc] | [prev] | [next] | [standalone]


#393123

FromLawrence D'Oliveiro <ldo@nz.invalid>
Date2025-05-03 22:47 +0000
Message-ID<vv66dt$hbt1$1@dont-email.me>
In reply to#393118
On Sat, 3 May 2025 01:14:46 -0700, Andrey Tarasevich wrote:

> Virtually every C project relies on assignment of structures.
> Passing-returning structs by value might be more rare (although
> perfectly valid and often appropriate too), but assignment...
> assignment is used by everyone everywhere without even giving it a
> second thought.

There is a caveat, to do with alignment padding: will this always have a 
defined value?

[toc] | [prev] | [next] | [standalone]


#393124

FromLawrence D'Oliveiro <ldo@nz.invalid>
Date2025-05-03 22:46 +0000
Message-ID<vv66c0$hbpd$5@dont-email.me>
In reply to#393118
On Sat, 3 May 2025 01:14:46 -0700, Andrey Tarasevich wrote:

> Virtually every C project relies on assignment of structures.
> Passing-returning structs by value might be more rare (although
> perfectly valid and often appropriate too), but assignment...
> assignment is used by everyone everywhere without even giving it a
> second thought.

There is a caveat, to do with alignment padding: will this always have a 
defined value?

[toc] | [prev] | [next] | [standalone]


#393134

FromTim Rentsch <tr.17687@z991.linuxsc.com>
Date2025-05-04 06:48 -0700
Message-ID<86plgo7ahu.fsf@linuxsc.com>
In reply to#393118
Andrey Tarasevich <noone@noone.net> writes:

> On Fri 5/2/2025 11:34 AM, Lew Pitcher wrote:
>
>> Back in the days of K&R, Kernighan and Ritchie published an addendum
>> to the "C Reference Manual" titled "Recent Changes to C" (November 1978)
>> in which they detailed some differences in the C language post "The
>> C Programming Language".
>>
>> The first difference they noted was that
>>    "Structures may be assigned, passed as arguments to functions, and
>>     returned by functions."
>>
>>  From what I can see of the ISO C standards, the current C language
>> has kept these these features.  However, I don't see many C projects
>> using them.
>
> Weird.  Virtually every C project relies on assignment of
> structures.  Passing-returning structs by value might be more rare
> (although perfectly valid and often appropriate too), but
> assignment... assignment is used by everyone everywhere without even
> giving it a second thought.
>
> 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?

[toc] | [prev] | [next] | [standalone]


#393161

FromAndrey Tarasevich <noone@noone.net>
Date2025-05-04 22:22 -0700
Message-ID<vv9hu7$3nomg$1@dont-email.me>
In reply to#393134
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...

-- 
Best regards,
Andrey

[toc] | [prev] | [next] | [standalone]


#393163

FromMichael S <already5chosen@yahoo.com>
Date2025-05-05 11:12 +0300
Message-ID<20250505111213.00004b55@yahoo.com>
In reply to#393161
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.

[toc] | [prev] | [next] | [standalone]


#393165

FromAndrey Tarasevich <noone@noone.net>
Date2025-05-05 01:29 -0700
Message-ID<vv9stv$2i8j$1@dont-email.me>
In reply to#393163
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);

So, what you are basing your "UB" claim on is not clear to me.

-- 
Best regards,
Andrey

[toc] | [prev] | [next] | [standalone]


#393168

FromMichael S <already5chosen@yahoo.com>
Date2025-05-05 12:01 +0300
Message-ID<20250505120145.000014f8@yahoo.com>
In reply to#393165
On Mon, 5 May 2025 01:29:47 -0700
Andrey Tarasevich <noone@noone.net> 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];

> So, what you are basing your "UB" claim on is not clear to me.
> 

If you read the post of Keith Thompson and it is still not clears to
you then I can not help.


[toc] | [prev] | [next] | [standalone]


#393176

FromTim Rentsch <tr.17687@z991.linuxsc.com>
Date2025-05-05 07:14 -0700
Message-ID<86wmav401y.fsf@linuxsc.com>
In reply to#393168
Michael S <already5chosen@yahoo.com> writes:

> On Mon, 5 May 2025 01:29:47 -0700
> Andrey Tarasevich <noone@noone.net> 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];
>
>> So, what you are basing your "UB" claim on is not clear to me.
>
> If you read the post of Keith Thompson and it is still not clears to
> you then I can not help.

Under C11 semantics, both

   int a5 = (a = b).a[5];
   
and

   int* pa5 = &(a = b).a[5];

have well-defined behavior.  The undefined behavior of the
upthread example comes later, only after the statement assigning
to the pointer (or here, initializing) completes.  It isn't
taking the address with & that has undefined behavior;  it is
using the stored pointer value in a subsequent statement, /after
the full expression containing the & operator has completed/,
that results in undefined behavior.

[toc] | [prev] | [next] | [standalone]


#393178

FromAndrey Tarasevich <noone@noone.net>
Date2025-05-05 08:45 -0700
Message-ID<vvame5$ppqp$1@dont-email.me>
In reply to#393168
On Mon 5/5/2025 2:01 AM, Michael S wrote:
> On Mon, 5 May 2025 01:29:47 -0700
> Andrey Tarasevich <noone@noone.net> 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]

- 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 <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", (void *) pa, (void *) pb, (void *) pc);
   }

This version has no UB.

-- 
Best regards,
Andrey

[toc] | [prev] | [next] | [standalone]


#393180

FromMichael S <already5chosen@yahoo.com>
Date2025-05-05 20:20 +0300
Message-ID<20250505202038.000034b9@yahoo.com>
In reply to#393178
On Mon, 5 May 2025 08:45:09 -0700
Andrey Tarasevich <noone@noone.net> wrote:

> On Mon 5/5/2025 2:01 AM, Michael S wrote:
> > On Mon, 5 May 2025 01:29:47 -0700
> > Andrey Tarasevich <noone@noone.net> 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 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 <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", (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.


[toc] | [prev] | [next] | [standalone]


#393198

FromTim Rentsch <tr.17687@z991.linuxsc.com>
Date2025-05-05 22:26 -0700
Message-ID<86r0122ttt.fsf@linuxsc.com>
In reply to#393180
Michael S <already5chosen@yahoo.com> writes:

> On Mon, 5 May 2025 08:45:09 -0700
> Andrey Tarasevich <noone@noone.net> wrote:
>
>> On Mon 5/5/2025 2:01 AM, Michael S wrote:
>>
>>> On Mon, 5 May 2025 01:29:47 -0700
>>> Andrey Tarasevich <noone@noone.net> 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 <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", (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.

[toc] | [prev] | [next] | [standalone]


Page 2 of 6 — ← Prev page 1 [2] 3 4 5 6  Next page →

Back to top | Article view | comp.lang.c


csiph-web