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.comvoid Void(void) { Void(); } /* The recursive call of the void */