Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.c > #158407 > unrolled thread
| Started by | wij <wyniijj@gmail.com> |
|---|---|
| First post | 2021-01-17 06:09 -0800 |
| Last post | 2021-01-17 17:17 +0000 |
| Articles | 20 on this page of 31 — 11 participants |
Back to article view | Back to comp.lang.c
Usage of union wij <wyniijj@gmail.com> - 2021-01-17 06:09 -0800
Re: Usage of union wij <wyniijj@gmail.com> - 2021-01-17 06:18 -0800
Re: Usage of union James Kuyper <jameskuyper@alumni.caltech.edu> - 2021-01-17 10:39 -0500
Re: Usage of union wij <wyniijj@gmail.com> - 2021-01-17 08:41 -0800
Re: Usage of union Lew Pitcher <lew.pitcher@digitalfreehold.ca> - 2021-01-17 17:07 +0000
Re: Usage of union James Kuyper <jameskuyper@alumni.caltech.edu> - 2021-01-17 12:29 -0500
Re: Usage of union Lew Pitcher <lew.pitcher@digitalfreehold.ca> - 2021-01-17 17:47 +0000
Re: Usage of union James Kuyper <jameskuyper@alumni.caltech.edu> - 2021-01-17 14:22 -0500
Re: Usage of union Tim Rentsch <tr.17687@z991.linuxsc.com> - 2021-01-20 07:03 -0800
Re: Usage of union wij <wyniijj@gmail.com> - 2021-01-20 09:33 -0800
Re: Usage of union Tim Rentsch <tr.17687@z991.linuxsc.com> - 2021-01-23 08:01 -0800
Re: Usage of union Jorgen Grahn <grahn+nntp@snipabacken.se> - 2021-01-26 20:28 +0000
Re: Usage of union wij <wyniijj@gmail.com> - 2021-01-27 03:15 -0800
Re: Usage of union James Kuyper <jameskuyper@alumni.caltech.edu> - 2021-01-17 12:19 -0500
Re: Usage of union Bonita Montero <Bonita.Montero@gmail.com> - 2021-01-20 19:24 +0100
Re: Usage of union Christian Hanné <the.hanne@gmail.com> - 2021-01-20 19:31 +0100
Re: Usage of union Andrey Tarasevich <andreytarasevich@hotmail.com> - 2021-01-17 07:54 -0800
Re: Usage of union Andrey Tarasevich <andreytarasevich@hotmail.com> - 2021-01-17 08:17 -0800
Re: Usage of union wij <wyniijj@gmail.com> - 2021-01-17 09:07 -0800
Re: Usage of union James Kuyper <jameskuyper@alumni.caltech.edu> - 2021-01-17 12:32 -0500
Re: Usage of union Tim Rentsch <tr.17687@z991.linuxsc.com> - 2021-01-20 05:56 -0800
Re: Usage of union Andrey Tarasevich <andreytarasevich@hotmail.com> - 2021-01-20 09:52 -0800
Re: Usage of union Tim Rentsch <tr.17687@z991.linuxsc.com> - 2021-01-20 06:09 -0800
Re: Usage of union Bonita Montero <Bonita.Montero@gmail.com> - 2021-01-20 19:41 +0100
Re: Usage of union scott@slp53.sl.home (Scott Lurndal) - 2021-01-20 18:49 +0000
Re: Usage of union Bonita Montero <Bonita.Montero@gmail.com> - 2021-01-20 20:09 +0100
Re: Usage of union scott@slp53.sl.home (Scott Lurndal) - 2021-01-20 19:25 +0000
Re: Usage of union David Brown <david.brown@hesbynett.no> - 2021-01-20 20:29 +0100
Re: Usage of union Andrey Tarasevich <andreytarasevich@hotmail.com> - 2021-01-20 11:36 -0800
Re: Usage of union James Kuyper <jameskuyper@alumni.caltech.edu> - 2021-01-17 12:14 -0500
Re: Usage of union Ben Bacarisse <ben.usenet@bsb.me.uk> - 2021-01-17 17:17 +0000
Page 1 of 2 [1] 2 Next page →
| From | wij <wyniijj@gmail.com> |
|---|---|
| Date | 2021-01-17 06:09 -0800 |
| Subject | Usage of union |
| Message-ID | <0f20fca0-ccf0-4f43-99f7-d2ed20d9f3b7n@googlegroups.com> |
My understanding of union is from the low level point of view, worked
so far OK. But confused again by reading the meaning of how C++11 says it treats union.
https://stackoverflow.com/questions/11373203/accessing-inactive-union-member-and-undefined-behavior
//-----------------------------
union {
uint16 u16;
uint8 u8[2];
float flt;
} u;
void t() {
u.u16=0;
assert(u.u8[0]==0); // using u8 member is UB
assert(u.u8[1]==0); // then, what does UB mean?
// might the lines above trigger Undefined Behavior?
};
//-----------------------------
If I store values via member u16, surely I CAN use other members.
What does UB really mean in this situation?
[toc] | [next] | [standalone]
| From | wij <wyniijj@gmail.com> |
|---|---|
| Date | 2021-01-17 06:18 -0800 |
| Message-ID | <d1f99f5b-39e5-41fb-b1b6-a58493736a71n@googlegroups.com> |
| In reply to | #158407 |
On Sunday, 17 January 2021 at 22:10:09 UTC+8, wij wrote:
> My understanding of union is from the low level point of view, worked
> so far OK. But confused again by reading the meaning of how C++11 says it treats union.
>
> https://stackoverflow.com/questions/11373203/accessing-inactive-union-member-and-undefined-behavior
>
> //-----------------------------
> union {
> uint16 u16;
> uint8 u8[2];
> float flt;
> } u;
>
> void t() {
> u.u16=0;
>
> assert(u.u8[0]==0); // using u8 member is UB
> assert(u.u8[1]==0); // then, what does UB mean?
> // might the lines above trigger Undefined Behavior?
> };
> //-----------------------------
>
> If I store values via member u16, surely I CAN use other members.
> What does UB really mean in this situation?
Sorry! My firefox browser (updated version!) can only sent "New conversation" to comp.lang.c.
But OK, I would also like to know how C treats union
[toc] | [prev] | [next] | [standalone]
| From | James Kuyper <jameskuyper@alumni.caltech.edu> |
|---|---|
| Date | 2021-01-17 10:39 -0500 |
| Message-ID | <ru1lna$4nl$1@dont-email.me> |
| In reply to | #158409 |
On 1/17/21 9:18 AM, wij wrote:
> On Sunday, 17 January 2021 at 22:10:09 UTC+8, wij wrote:
>> My understanding of union is from the low level point of view, worked
>> so far OK. But confused again by reading the meaning of how C++11 says it treats union.
>>
>> https://stackoverflow.com/questions/11373203/accessing-inactive-union-member-and-undefined-behavior
>>
>> //-----------------------------
>> union {
>> uint16 u16;
>> uint8 u8[2];
>> float flt;
>> } u;
>>
>> void t() {
>> u.u16=0;
>>
>> assert(u.u8[0]==0); // using u8 member is UB
>> assert(u.u8[1]==0); // then, what does UB mean?
>> // might the lines above trigger Undefined Behavior?
>> };
>> //-----------------------------
>>
>> If I store values via member u16, surely I CAN use other members.
>> What does UB really mean in this situation?
>
> Sorry! My firefox browser (updated version!) can only sent "New conversation" to comp.lang.c.
> But OK, I would also like to know how C treats union
Reading from a different member of a union than the one last written to
used to have implementation-defined behavior, but in C2011, section
6.5.2.3p3 was changed to refers to the new footnote 95, which specifies:
"If the member used to read the contents of a union object is not the
same as the member last used to store a value in the object, the
appropriate part of the object representation of the value is
reinterpreted as an object representation in the new type as described
in 6.2.6 (a process sometimes called ‘‘type punning’’). This might be a
trap representation."
Footnotes are not themselves normative; they're supposed to clarify
conclusions that are reliably deducible from the normative text, but are
not necessarily obvious. What Footnote 95 says supposedly derives from
what the normative text says about object representations, but I don't
see how, and I've never seen a valid derivation of that specification
from the normative text.
However, what it specifies is the same as the implementation-defined
behavior on almost every C implementation that existed before C2011 came
out, and a large amount of C code was written to rely upon such
behavior. Therefore, I recommend treating it as if there was supporting
normative text, even if there isn't.
Note that, since the representation of types is not completely standard
specified for any type, and is entirely implementation-defined for many
types, there's virtually no portable way to take advantage of this fact.
For example, there's no guarantee which bits of u16 are zeroed by
execution of u8[0] = 0. It could, for instance, be only the odd-numbered
bits (though that would require a VERY unusual architecture).
[toc] | [prev] | [next] | [standalone]
| From | wij <wyniijj@gmail.com> |
|---|---|
| Date | 2021-01-17 08:41 -0800 |
| Message-ID | <12db7b19-3ba3-4562-aee9-51531a52fcf3n@googlegroups.com> |
| In reply to | #158411 |
On Sunday, 17 January 2021 at 23:39:34 UTC+8, james...@alumni.caltech.edu wrote: ... > Note that, since the representation of types is not completely standard > specified for any type, and is entirely implementation-defined for many > types, there's virtually no portable way to take advantage of this fact. > For example, there's no guarantee which bits of u16 are zeroed by > execution of u8[0] = 0. It could, for instance, be only the odd-numbered > bits (though that would require a VERY unusual architecture). Understandable. But: 1. Will such a writing "assert(u.u8[0]==0);" cause UB? 2. Using u8 access bit-pattern of floating number (e.g. flt) a UB? What if I interpret the UB in this condition as "non-portable" or "implementation-defined"? I just don't see the point declaring it as UB.
[toc] | [prev] | [next] | [standalone]
| From | Lew Pitcher <lew.pitcher@digitalfreehold.ca> |
|---|---|
| Date | 2021-01-17 17:07 +0000 |
| Message-ID | <ru1qs7$hht$1@dont-email.me> |
| In reply to | #158414 |
On Sun, 17 Jan 2021 08:41:29 -0800, wij wrote:
> On Sunday, 17 January 2021 at 23:39:34 UTC+8,
> james...@alumni.caltech.edu wrote:
> ...
>> Note that, since the representation of types is not completely standard
>> specified for any type, and is entirely implementation-defined for many
>> types, there's virtually no portable way to take advantage of this
>> fact.
>> For example, there's no guarantee which bits of u16 are zeroed by
>> execution of u8[0] = 0. It could, for instance, be only the
>> odd-numbered bits (though that would require a VERY unusual
>> architecture).
>
> Understandable. But:
For context, here's the relevant part of the OP:
//-----------------------------
union {
uint16 u16;
uint8 u8[2];
float flt;
} u;
void t() {
u.u16=0;
assert(u.u8[0]==0);
> 1. Will such a writing "assert(u.u8[0]==0);" cause UB?
Yes. The prior code does not store a value in u.u8[0]; u.u8[0],
therefore, holds an indeterminate value. This equality test, by it's
nature, must retrieve a value from u.u8[0]. The C standard /does not
define/ the results of such an access (nor, for that matter, the results
of an equality test with an indeterminate value) and thus, the assert()
statement invokes "undefined behaviour".
> 2. Using u8 access bit-pattern of floating number (e.g. flt) a UB?
Yes. Again, for the same reasons as above.
> What if I interpret the UB in this condition as "non-portable" or
> "implementation-defined"?
In the C standard, "implementation-defined" has a different meaning than
"undefined behaviour". The standard allows the implementations some
latitude in how they implement certain requirements, and indicates these
allowances as "implementation-defined". Your interpretation of UB as
"implementation defined" does not hold.
Having said that, in practical terms, you probably could "get away" with
treating UB as "implementation-defined", so long as you realize that such
behaviour /is not guaranteed/, release-to-release, or even within a
specific release of a C language implementation. What works today might
not work tomorrow, or might give incorrect or inconsistent results,
execution to execution, and you /cannot/ depend on that behaviour to
remain consistent.
Although, some programmers /do/.
> I just don't see the point declaring it as UB.
They declare it as "undefined behaviour" in the same way that the
Websters dictionary defines "aswertfdvasetqwertqwvreesrfg" as an
"undefined word"; in other words; they /DON'T/ define it.
"Undefined behaviour" simply means that the standard /DOES NOT/ define
what will happen, not even to say that the implementation can choose how
to handle the operation.
HTH
--
Lew Pitcher
"In Skills, We Trust"
[toc] | [prev] | [next] | [standalone]
| From | James Kuyper <jameskuyper@alumni.caltech.edu> |
|---|---|
| Date | 2021-01-17 12:29 -0500 |
| Message-ID | <ru1s6n$k0b$1@dont-email.me> |
| In reply to | #158415 |
On 1/17/21 12:07 PM, Lew Pitcher wrote:
> On Sun, 17 Jan 2021 08:41:29 -0800, wij wrote:
>
>> On Sunday, 17 January 2021 at 23:39:34 UTC+8,
>> james...@alumni.caltech.edu wrote:
>> ...
>>> Note that, since the representation of types is not completely standard
>>> specified for any type, and is entirely implementation-defined for many
>>> types, there's virtually no portable way to take advantage of this
>>> fact.
>>> For example, there's no guarantee which bits of u16 are zeroed by
>>> execution of u8[0] = 0. It could, for instance, be only the
>>> odd-numbered bits (though that would require a VERY unusual
>>> architecture).
>>
>> Understandable. But:
> For context, here's the relevant part of the OP:
>
> //-----------------------------
> union {
> uint16 u16;
> uint8 u8[2];
> float flt;
> } u;
>
> void t() {
> u.u16=0;
>
> assert(u.u8[0]==0);
>
>
>> 1. Will such a writing "assert(u.u8[0]==0);" cause UB?
>
> Yes. The prior code does not store a value in u.u8[0]; u.u8[0],
> therefore, holds an indeterminate value. This equality test, by it's
> nature, must retrieve a value from u.u8[0]. The C standard /does not
> define/ the results of such an access
Are you denying the validity of Footnote 95? It's not normative text,
but it's supposed to be an accurate summary of what is said elsewhere in
normative text. I've been told by a committee member that this is indeed
the case, but they failed to respond to my request for identification of
the supporting normative text.
>> What if I interpret the UB in this condition as "non-portable" or
>> "implementation-defined"?
>
> In the C standard, "implementation-defined" has a different meaning than
> "undefined behaviour". The standard allows the implementations some
> latitude in how they implement certain requirements, and indicates these
> allowances as "implementation-defined". Your interpretation of UB as
> "implementation defined" does not hold.
>
> Having said that, in practical terms, you probably could "get away" with
> treating UB as "implementation-defined", so long as you realize that such
When the behavior is implementation-defined, there's a set (possibly
infinite in size) of permitted behaviors. If your code deals properly
with all elements in that set, it will work as specified. There's no way
to do that when the behavior is undefined.
When the behavior is implementation-defined, it is required to be the
case that you can examine the implementation's documentation to
determine what that behavior actually is. That's not true when the
behavior is undefined.
>> I just don't see the point declaring it as UB.
>
> They declare it as "undefined behaviour" in the same way that the
> Websters dictionary defines "aswertfdvasetqwertqwvreesrfg" as an
> "undefined word"; in other words; they /DON'T/ define it.
That's only one of the three ways undefined behavior is specified by the
C standard:
"Undefined behavior is otherwise indicated in this International
Standard by the words ‘‘undefined behavior’’ or by the omission of any
explicit definition of behavior. There is no difference in emphasis
among these three; they all describe ‘‘behavior that is undefined’’." (4p6)
However, none of those ways apply to this case (unless Footnote 95 is
incorrect).
[toc] | [prev] | [next] | [standalone]
| From | Lew Pitcher <lew.pitcher@digitalfreehold.ca> |
|---|---|
| Date | 2021-01-17 17:47 +0000 |
| Message-ID | <ru1t7d$hht$2@dont-email.me> |
| In reply to | #158420 |
On Sun, 17 Jan 2021 12:29:58 -0500, James Kuyper wrote:
> On 1/17/21 12:07 PM, Lew Pitcher wrote:
>> On Sun, 17 Jan 2021 08:41:29 -0800, wij wrote:
>>
>>> On Sunday, 17 January 2021 at 23:39:34 UTC+8,
>>> james...@alumni.caltech.edu wrote:
>>> ...
>>>> Note that, since the representation of types is not completely
>>>> standard specified for any type, and is entirely
>>>> implementation-defined for many types, there's virtually no portable
>>>> way to take advantage of this fact.
>>>> For example, there's no guarantee which bits of u16 are zeroed by
>>>> execution of u8[0] = 0. It could, for instance, be only the
>>>> odd-numbered bits (though that would require a VERY unusual
>>>> architecture).
>>>
>>> Understandable. But:
>> For context, here's the relevant part of the OP:
>>
>> //-----------------------------
>> union {
>> uint16 u16;
>> uint8 u8[2]; float flt;
>> } u;
>>
>> void t() {
>> u.u16=0;
>>
>> assert(u.u8[0]==0);
>>
>>
>>> 1. Will such a writing "assert(u.u8[0]==0);" cause UB?
>>
>> Yes. The prior code does not store a value in u.u8[0]; u.u8[0],
>> therefore, holds an indeterminate value. This equality test, by it's
>> nature, must retrieve a value from u.u8[0]. The C standard /does not
>> define/ the results of such an access
>
> Are you denying the validity of Footnote 95?
No, James, I'm asserting my personal understanding of the subject.
Admittedly, my understanding may be wrong or incomplete, and I welcome
your efforts to clarify and expand it.
--
Lew Pitcher
"In Skills, We Trust"
[toc] | [prev] | [next] | [standalone]
| From | James Kuyper <jameskuyper@alumni.caltech.edu> |
|---|---|
| Date | 2021-01-17 14:22 -0500 |
| Message-ID | <ru22os$35d$1@dont-email.me> |
| In reply to | #158420 |
On 1/17/21 12:29 PM, James Kuyper wrote: > On 1/17/21 12:07 PM, Lew Pitcher wrote: ... >> They declare it as "undefined behaviour" in the same way that the >> Websters dictionary defines "aswertfdvasetqwertqwvreesrfg" as an >> "undefined word"; in other words; they /DON'T/ define it. > > That's only one of the three ways undefined behavior is specified by the > C standard: > > "Undefined behavior is otherwise indicated in this International > Standard by the words ‘‘undefined behavior’’ or by the omission of any > explicit definition of behavior. There is no difference in emphasis > among these three; they all describe ‘‘behavior that is undefined’’." (4p6) That's only two ways. I made a mistake when copy and pasting, and left our the first of the three ways: "If a ‘‘shall’’ or ‘‘shall not’’ requirement that appears outside of a constraint or runtime-constraint is violated, the behavior is undefined."
[toc] | [prev] | [next] | [standalone]
| From | Tim Rentsch <tr.17687@z991.linuxsc.com> |
|---|---|
| Date | 2021-01-20 07:03 -0800 |
| Message-ID | <86lfcnodl3.fsf@linuxsc.com> |
| In reply to | #158415 |
Lew Pitcher <lew.pitcher@digitalfreehold.ca> writes:
> On Sun, 17 Jan 2021 08:41:29 -0800, wij wrote:
>
>> On Sunday, 17 January 2021 at 23:39:34 UTC+8,
>> james...@alumni.caltech.edu wrote:
>> ...
>>
>>> Note that, since the representation of types is not completely standard
>>> specified for any type, and is entirely implementation-defined for many
>>> types, there's virtually no portable way to take advantage of this
>>> fact.
>>> For example, there's no guarantee which bits of u16 are zeroed by
>>> execution of u8[0] = 0. It could, for instance, be only the
>>> odd-numbered bits (though that would require a VERY unusual
>>> architecture).
>>
>> Understandable. But:
>
> For context, here's the relevant part of the OP:
>
> //-----------------------------
> union {
> uint16 u16; [understood to mean uint16_t]
> uint8 u8[2]; [understood to mean uint8_t]
> float flt;
> } u;
>
> void t() {
> u.u16=0;
>
> assert(u.u8[0]==0);
>
>
>> 1. Will such a writing "assert(u.u8[0]==0);" cause UB?
>
> Yes. The prior code does not store a value in u.u8[0]; u.u8[0],
> therefore, holds an indeterminate value. [...]
This is wrong. The objects for u.u8[0] and u.u16 overlap.
After assigning to u.u16, u.u8[0] holds the first 8 bits of the
object representation of the value stored in u.u16. We know
those bits must all be zero. We also know that the abstract
value for the object representation (of u.u8[0]) of all bits
zero will be 0. Thus the access is well defined and must yield
the value 0, so the assert(u.u8[0]==0) must succeed. There is
no undefined behavior, or even the possibility of undefined
behavior. (Note the "understood to mean" annotations in the
above quoted code. Different types could mean different
conclusions.)
The above statements apply to C, but not to C++. In C++ the
rules for union members are different, and the access of u.u8[0]
is undefined behavior, because it is being accessed outside of
its lifetime.
[toc] | [prev] | [next] | [standalone]
| From | wij <wyniijj@gmail.com> |
|---|---|
| Date | 2021-01-20 09:33 -0800 |
| Message-ID | <8a82ee84-8053-491c-95a0-c4371cd65672n@googlegroups.com> |
| In reply to | #158481 |
On Wednesday, 20 January 2021 at 23:03:38 UTC+8, Tim Rentsch wrote:
> Lew Pitcher <lew.p...@digitalfreehold.ca> writes:
>
> > On Sun, 17 Jan 2021 08:41:29 -0800, wij wrote:
> >
> >> On Sunday, 17 January 2021 at 23:39:34 UTC+8,
> >> james...@alumni.caltech.edu wrote:
> >> ...
> >>
> >>> Note that, since the representation of types is not completely standard
> >>> specified for any type, and is entirely implementation-defined for many
> >>> types, there's virtually no portable way to take advantage of this
> >>> fact.
> >>> For example, there's no guarantee which bits of u16 are zeroed by
> >>> execution of u8[0] = 0. It could, for instance, be only the
> >>> odd-numbered bits (though that would require a VERY unusual
> >>> architecture).
> >>
> >> Understandable. But:
> >
> > For context, here's the relevant part of the OP:
> >
> > //-----------------------------
> > union {
> > uint16 u16; [understood to mean uint16_t]
> > uint8 u8[2]; [understood to mean uint8_t]
> > float flt;
> > } u;
> >
> > void t() {
> > u.u16=0;
> >
> > assert(u.u8[0]==0);
> >
> >
> >> 1. Will such a writing "assert(u.u8[0]==0);" cause UB?
> >
> > Yes. The prior code does not store a value in u.u8[0]; u.u8[0],
> > therefore, holds an indeterminate value. [...]
>
> This is wrong. The objects for u.u8[0] and u.u16 overlap.
> After assigning to u.u16, u.u8[0] holds the first 8 bits of the
> object representation of the value stored in u.u16. We know
> those bits must all be zero. We also know that the abstract
> value for the object representation (of u.u8[0]) of all bits
> zero will be 0. Thus the access is well defined and must yield
> the value 0, so the assert(u.u8[0]==0) must succeed. There is
> no undefined behavior, or even the possibility of undefined
> behavior. (Note the "understood to mean" annotations in the
> above quoted code. Different types could mean different
> conclusions.)
>
> The above statements apply to C, but not to C++. In C++ the
> rules for union members are different, and the access of u.u8[0]
> is undefined behavior,
C++ is a top-down language (developed by elites). But it also has to build on
C or something C has provided, because at least, low level things to my
knowledge are mostly governed by C or C compatible way.
So, if no surprise, I think 'traditional' C way of using union is fine, otherwise the
compiler should consider give warnings or errors.
>...because it is being accessed outside of
> its lifetime.
In lawyer (language specialist) way of speaking, object uint8_t is never created
, so no such thing as 'lifetime'. (kidding)
[toc] | [prev] | [next] | [standalone]
| From | Tim Rentsch <tr.17687@z991.linuxsc.com> |
|---|---|
| Date | 2021-01-23 08:01 -0800 |
| Message-ID | <86zh0zmym1.fsf@linuxsc.com> |
| In reply to | #158490 |
wij <wyniijj@gmail.com> writes:
> On Wednesday, 20 January 2021 at 23:03:38 UTC+8, Tim Rentsch wrote:
>
>> Lew Pitcher <lew.p...@digitalfreehold.ca> writes:
>>
>>> On Sun, 17 Jan 2021 08:41:29 -0800, wij wrote:
>>>
>>>> On Sunday, 17 January 2021 at 23:39:34 UTC+8,
>>>> james...@alumni.caltech.edu wrote:
>>>> ...
>>>>
>>>>> Note that, since the representation of types is not completely standard
>>>>> specified for any type, and is entirely implementation-defined for many
>>>>> types, there's virtually no portable way to take advantage of this
>>>>> fact.
>>>>> For example, there's no guarantee which bits of u16 are zeroed by
>>>>> execution of u8[0] = 0. It could, for instance, be only the
>>>>> odd-numbered bits (though that would require a VERY unusual
>>>>> architecture).
>>>>
>>>> Understandable. But:
>>>
>>> For context, here's the relevant part of the OP:
>>>
>>> //-----------------------------
>>> union {
>>> uint16 u16; [understood to mean uint16_t]
>>> uint8 u8[2]; [understood to mean uint8_t]
>>> float flt;
>>> } u;
>>>
>>> void t() {
>>> u.u16=0;
>>>
>>> assert(u.u8[0]==0);
>>>
>>>
>>>> 1. Will such a writing "assert(u.u8[0]==0);" cause UB?
>>>
>>> Yes. The prior code does not store a value in u.u8[0]; u.u8[0],
>>> therefore, holds an indeterminate value. [...]
>>
>> This is wrong. The objects for u.u8[0] and u.u16 overlap.
>> After assigning to u.u16, u.u8[0] holds the first 8 bits of the
>> object representation of the value stored in u.u16. We know
>> those bits must all be zero. We also know that the abstract
>> value for the object representation (of u.u8[0]) of all bits
>> zero will be 0. Thus the access is well defined and must yield
>> the value 0, so the assert(u.u8[0]==0) must succeed. There is
>> no undefined behavior, or even the possibility of undefined
>> behavior. (Note the "understood to mean" annotations in the
>> above quoted code. Different types could mean different
>> conclusions.)
>>
>> The above statements apply to C, but not to C++. In C++ the
>> rules for union members are different, and the access of u.u8[0]
>> is undefined behavior,
>
> C++ is a top-down language (developed by elites). But it also has
> to build on C or something C has provided, because at least, low
> level things to my knowledge are mostly governed by C or C
> compatible way.
> So, if no surprise, I think 'traditional' C way of using union is
> fine, otherwise the compiler should consider give warnings or
> errors.
The C++ standards group has decided that the rules for union
member access do not match the C rules. That's just how it is.
As for giving some sort of warning/error, that is not workable in
any practical sense, because the question is undecidable, and
even fairly common real-world scenarios are too difficult to
diagnose effectively.
>> ...because it is being accessed outside of
>> its lifetime.
>
> In lawyer (language specialist) way of speaking, object uint8_t is
> never created , so no such thing as 'lifetime'. (kidding)
The C++ standard gives specific rules for the lifetimes of
objects in general and of union member objects in particular, and
those rules don't match the C rules for object lifetimes in the
particular case of union member objects.
[toc] | [prev] | [next] | [standalone]
| From | Jorgen Grahn <grahn+nntp@snipabacken.se> |
|---|---|
| Date | 2021-01-26 20:28 +0000 |
| Message-ID | <slrns10urq.2ptb.grahn+nntp@frailea.sa.invalid> |
| In reply to | #158490 |
On Wed, 2021-01-20, wij wrote: > C++ is a top-down language (developed by elites). C and C++ were both designed by people in the same corridor at Bell Labs. /Jorgen -- // Jorgen Grahn <grahn@ Oo o. . . \X/ snipabacken.se> O o .
[toc] | [prev] | [next] | [standalone]
| From | wij <wyniijj@gmail.com> |
|---|---|
| Date | 2021-01-27 03:15 -0800 |
| Message-ID | <52f2bd03-7aa4-4ac7-9ffd-1499528fd005n@googlegroups.com> |
| In reply to | #158637 |
On Wednesday, 27 January 2021 at 04:28:55 UTC+8, Jorgen Grahn wrote:
> On Wed, 2021-01-20, wij wrote:
> > C++ is a top-down language (developed by elites).
> C and C++ were both designed by people in the same corridor
> at Bell Labs.
>
> /Jorgen
>
> --
> // Jorgen Grahn <grahn@ Oo o. . .
> \X/ snipabacken.se> O o .
Dennis Ritchie and Bjarne Stroustrup were at AT&T Bell Labs, and were friends.
That was just it.
C can be said a portable assembly. It HAS TO deal with various hardware
features/things to build an OS, regardless of how and what high level
spec. (standard) says. (but hardware API is also often specified in C or
assembly.) I did not actually write C for more than 2-decays, this is my
current opinion.
C++ was based on 'concept'(class), therefore the associated abstract operator
(name) overloads to support it,...and many subsequent branches follow.
Among which, the basics are class inheritance and error handling (exception)
unfortunately, class inheritance (the IS-A) rule is defective (think about UML).
And, to my knowledge, B.S. did not like how 'exception' was and has no power
over it (i.e. C++ in all was developed by a group of people from the very begining)
IMO, many things in C++ are invented by 'elites' or smart ideas once poped-up
then standardize in about 3-years period without demands out from longer
enough space-time practical experiences. I think this the differences with C.
I have less problem of new inventions than about the previous defects found
latter (e.g. I still think rref a defect: the functionality is simple, while it adds
thousands difficult pages to the spec., just does not seem right)
Therefore, I personally do not use C++ standard library (but as a reference),
in fears that writing test codes would reveal many 'standard bugs' that I hate
to fight with.
Quote from https://www.hyrumslaw.com/
ALSO: https://nordicapis.com/what-does-hyrums-law-mean-for-api-design/
---------------------------------------------------------------------
An observation on Software Engineering
Put succinctly, the observation is this:
With a sufficient number of users of an API,
it does not matter what you promise in the contract:
all observable behaviors of your system
will be depended on by somebody.
...
...
-------------------------------------------------------------------
BTW, C/C++ standard might not be an API, and I cannot digest all standard spec.
I had fights against 'exception', STL, ... recently, 0.999...≠1, nicotine...etc.
Fighting against standard(average knowledge) is not a pleasant thing. Also
unfortunately, many still brewing in my head.
[toc] | [prev] | [next] | [standalone]
| From | James Kuyper <jameskuyper@alumni.caltech.edu> |
|---|---|
| Date | 2021-01-17 12:19 -0500 |
| Message-ID | <ru1rjd$fea$1@dont-email.me> |
| In reply to | #158414 |
On 1/17/21 11:41 AM, wij wrote: > On Sunday, 17 January 2021 at 23:39:34 UTC+8, james...@alumni.caltech.edu wrote: > ... >> Note that, since the representation of types is not completely standard >> specified for any type, and is entirely implementation-defined for many >> types, there's virtually no portable way to take advantage of this fact. >> For example, there's no guarantee which bits of u16 are zeroed by >> execution of u8[0] = 0. It could, for instance, be only the odd-numbered >> bits (though that would require a VERY unusual architecture). > > Understandable. But: > > 1. Will such a writing "assert(u.u8[0]==0);" cause UB? No, it's only writing that can be a problem. > 2. Using u8 access bit-pattern of floating number (e.g. flt) a UB? I addressed that issue in separate message that I just posted before reading this one. > What if I interpret the UB in this condition as "non-portable" or "implementation-defined"? > I just don't see the point declaring it as UB. "non-portable" has no standard-defined meaning. "implementation-defined" requires that the standard provide a set of options, and the implementation's documentation must identify which choice it made from that set. That is precisely what the C standard said until C2011. It has never said that the behavior is undefined.
[toc] | [prev] | [next] | [standalone]
| From | Bonita Montero <Bonita.Montero@gmail.com> |
|---|---|
| Date | 2021-01-20 19:24 +0100 |
| Message-ID | <ru9sho$ad$1@dont-email.me> |
| In reply to | #158411 |
> However, what it specifies is the same as the implementation-defined > behavior on almost every C implementation that existed before C2011 > came out, and a large amount of C code was written to rely upon such > behavior. Therefore, I recommend treating it as if there was supporting > normative text, even if there isn't. Even what wij did isn't portable because of endianess. > Note that, since the representation of types is not completely standard > specified for any type, and is entirely implementation-defined for many > types, there's virtually no portable way to take advantage of this fact. > For example, there's no guarantee which bits of u16 are zeroed by > execution of u8[0] = 0. It could, for instance, be only the odd-numbered > bits (though that would require a VERY unusual architecture). Nonsense. Such an architecture did never exist and will never exist because it wouldn't make any sense to design it that way.
[toc] | [prev] | [next] | [standalone]
| From | Christian Hanné <the.hanne@gmail.com> |
|---|---|
| Date | 2021-01-20 19:31 +0100 |
| Message-ID | <ru9stc$6ps$1@gioia.aioe.org> |
| In reply to | #158494 |
>> However, what it specifies is the same as the implementation-defined >> behavior on almost every C implementation that existed before C2011 >> came out, and a large amount of C code was written to rely upon such >> behavior. Therefore, I recommend treating it as if there was supporting >> normative text, even if there isn't. > Even what wij did isn't portable because of endianess. ... when accessing the float.
[toc] | [prev] | [next] | [standalone]
| From | Andrey Tarasevich <andreytarasevich@hotmail.com> |
|---|---|
| Date | 2021-01-17 07:54 -0800 |
| Message-ID | <ru1mk1$asv$1@dont-email.me> |
| In reply to | #158407 |
On 1/17/2021 6:09 AM, wij wrote:
> My understanding of union is from the low level point of view, worked
> so far OK. But confused again by reading the meaning of how C++11 says it treats union.
>
> https://stackoverflow.com/questions/11373203/accessing-inactive-union-member-and-undefined-behavior
>
> //-----------------------------
> union {
> uint16 u16;
> uint8 u8[2];
> float flt;
> } u;
>
> void t() {
> u.u16=0;
>
> assert(u.u8[0]==0); // using u8 member is UB
> assert(u.u8[1]==0); // then, what does UB mean?
> // might the lines above trigger Undefined Behavior?
> };
> //-----------------------------
>
> If I store values via member u16, surely I CAN use other members.
What do you mean by "use"? Write one member and then read another, as in
the above example? You _can_ do it in C, as long as you know what you
are doing. You _cannot_ do it in C++, since in C++ the behavior is
undefined.
In the above example you are trying to use union for "type punning", i.e
for memory reinterpretation. This is not exactly what unions are for.
And even though C generally permits type punning through unions, this
does not protect you from running into a trap representation (an
"invalid" value of target type) as result of such type punning. Which
leads to UB in C as well.
> What does UB really mean in this situation?
What do you mean by "use"? Write one member and then read another, as in
the above example? You _can_ do it in C, as long as you know what you
are doing. You _cannot_ do it in C++, since in C++ the behavior is
undefined.
In the above example you are trying to use union for "type punning", i.e
for memory reinterpretation. This is not exactly what unions are for.
And even though C generally permits type punning through unions, this
does not protect you from running into a trap representation (an
"invalid" value of target type) as result of such type punning. Which
leads to UB in C as well.
--
Best regards,
Andrey Tarasevich
[toc] | [prev] | [next] | [standalone]
| From | Andrey Tarasevich <andreytarasevich@hotmail.com> |
|---|---|
| Date | 2021-01-17 08:17 -0800 |
| Message-ID | <ru1nv2$k8v$1@dont-email.me> |
| In reply to | #158412 |
On 1/17/2021 7:54 AM, Andrey Tarasevich wrote:
> On 1/17/2021 6:09 AM, wij wrote:
>> My understanding of union is from the low level point of view, worked
>> so far OK. But confused again by reading the meaning of how C++11 says
>> it treats union.
>>
>>
https://stackoverflow.com/questions/11373203/accessing-inactive-union-member-and-undefined-behavior
>>
>>
>> //-----------------------------
>> union {
>> uint16 u16;
>> uint8 u8[2];
>> float flt;
>> } u;
>>
>> void t() {
>> u.u16=0;
>>
>> assert(u.u8[0]==0); // using u8 member is UB
>> assert(u.u8[1]==0); // then, what does UB mean?
>> // might the lines above trigger Undefined
>> Behavior?
>> };
>> //-----------------------------
>>
>> If I store values via member u16, surely I CAN use other members.
>
> What do you mean by "use"? Write one member and then read another, as in
> the above example? You _can_ do it in C, as long as you know what you
> are doing. You _cannot_ do it in C++, since in C++ the behavior is
> undefined.
>
> In the above example you are trying to use union for "type punning", i.e
> for memory reinterpretation. This is not exactly what unions are for.
>
> And even though C generally permits type punning through unions, this
> does not protect you from running into a trap representation (an
> "invalid" value of target type) as result of such type punning. Which
> leads to UB in C as well.
>
>> What does UB really mean in this situation?
>
Oops... A copy-pasting error (and overly long lines?). This should have
been:
UB means the same thing it always means: anything can happen.
For example, in C++ the compiler is free to assume that any changes to
`u16` have no effect on `u8`, even though these members overlap in the
union.
A C compiler is not allowed to make this assumption and there's no
immediate UB when reading `u8`. In general case the potential for UB is
still there (i.e. trap representation mentioned above), but with
`uint8_t` everything should be fine since `uint8_t` is not supposed to
have trap representations. (BTW, it seems that this is not explicitly
spelled out in C standard.)
--
Best regards,
Andrey Tarasevich
[toc] | [prev] | [next] | [standalone]
| From | wij <wyniijj@gmail.com> |
|---|---|
| Date | 2021-01-17 09:07 -0800 |
| Message-ID | <d170e627-a5de-430a-b078-e634e121b6c1n@googlegroups.com> |
| In reply to | #158413 |
On Monday, 18 January 2021 at 00:17:49 UTC+8, Andrey Tarasevich wrote:
> On 1/17/2021 7:54 AM, Andrey Tarasevich wrote:
> > On 1/17/2021 6:09 AM, wij wrote:
> >> My understanding of union is from the low level point of view, worked
> >> so far OK. But confused again by reading the meaning of how C++11 says
> >> it treats union.
> >>
> >>
> https://stackoverflow.com/questions/11373203/accessing-inactive-union-member-and-undefined-behavior
>
> >>
> >>
> >> //-----------------------------
> >> union {
> >> uint16 u16;
> >> uint8 u8[2];
> >> float flt;
> >> } u;
> >>
> >> void t() {
> >> u.u16=0;
> >>
> >> assert(u.u8[0]==0); // using u8 member is UB
> >> assert(u.u8[1]==0); // then, what does UB mean?
> >> // might the lines above trigger Undefined
> >> Behavior?
> >> };
> >> //-----------------------------
> >>
> >> If I store values via member u16, surely I CAN use other members.
> >
> > What do you mean by "use"? Write one member and then read another, as in
> > the above example? You _can_ do it in C, as long as you know what you
> > are doing. You _cannot_ do it in C++, since in C++ the behavior is
> > undefined.
> >
> > In the above example you are trying to use union for "type punning", i.e
> > for memory reinterpretation. This is not exactly what unions are for.
> >
> > And even though C generally permits type punning through unions, this
> > does not protect you from running into a trap representation (an
> > "invalid" value of target type) as result of such type punning. Which
> > leads to UB in C as well.
> >
> >> What does UB really mean in this situation?
> >
> Oops... A copy-pasting error (and overly long lines?). This should have
> been:
>
> UB means the same thing it always means: anything can happen.
>
> For example, in C++ the compiler is free to assume that any changes to
> `u16` have no effect on `u8`, even though these members overlap in the
> union.
>
Correction: uint16/uint8 should have been typed as uint16_t/uint8_t
> A C compiler is not allowed to make this assumption and there's no
> immediate UB when reading `u8`. In general case the potential for UB is
> still there (i.e. trap representation mentioned above), but with
> `uint8_t` everything should be fine since `uint8_t` is not supposed to
> have trap representations. (BTW, it seems that this is not explicitly
> spelled out in C standard.)
> --
> Best regards,
> Andrey Tarasevich
Good to hear that
[toc] | [prev] | [next] | [standalone]
| From | James Kuyper <jameskuyper@alumni.caltech.edu> |
|---|---|
| Date | 2021-01-17 12:32 -0500 |
| Message-ID | <ru1sbp$k0b$2@dont-email.me> |
| In reply to | #158413 |
On 1/17/21 11:17 AM, Andrey Tarasevich wrote: > On 1/17/2021 7:54 AM, Andrey Tarasevich wrote: > > On 1/17/2021 6:09 AM, wij wrote: ... > >> What does UB really mean in this situation? > > > > Oops... A copy-pasting error (and overly long lines?). This should have > been: > > UB means the same thing it always means: anything can happen. More precisely, the C standard doesn't prohibit anything from happening. Other things (such as the laws of physics or the POSIX standard) might prohibit some particular outcomes, even if the C standard does not.
[toc] | [prev] | [next] | [standalone]
Page 1 of 2 [1] 2 Next page →
Back to top | Article view | comp.lang.c
csiph-web