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


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

Usage of union

Started bywij <wyniijj@gmail.com>
First post2021-01-17 06:09 -0800
Last post2021-01-17 17:17 +0000
Articles 20 on this page of 31 — 11 participants

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


Contents

  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 →


#158407 — Usage of union

Fromwij <wyniijj@gmail.com>
Date2021-01-17 06:09 -0800
SubjectUsage 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]


#158409

Fromwij <wyniijj@gmail.com>
Date2021-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]


#158411

FromJames Kuyper <jameskuyper@alumni.caltech.edu>
Date2021-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]


#158414

Fromwij <wyniijj@gmail.com>
Date2021-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]


#158415

FromLew Pitcher <lew.pitcher@digitalfreehold.ca>
Date2021-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]


#158420

FromJames Kuyper <jameskuyper@alumni.caltech.edu>
Date2021-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]


#158422

FromLew Pitcher <lew.pitcher@digitalfreehold.ca>
Date2021-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]


#158425

FromJames Kuyper <jameskuyper@alumni.caltech.edu>
Date2021-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]


#158481

FromTim Rentsch <tr.17687@z991.linuxsc.com>
Date2021-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]


#158490

Fromwij <wyniijj@gmail.com>
Date2021-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]


#158575

FromTim Rentsch <tr.17687@z991.linuxsc.com>
Date2021-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]


#158637

FromJorgen Grahn <grahn+nntp@snipabacken.se>
Date2021-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]


#158642

Fromwij <wyniijj@gmail.com>
Date2021-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]


#158419

FromJames Kuyper <jameskuyper@alumni.caltech.edu>
Date2021-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]


#158494

FromBonita Montero <Bonita.Montero@gmail.com>
Date2021-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]


#158495

FromChristian Hanné <the.hanne@gmail.com>
Date2021-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]


#158412

FromAndrey Tarasevich <andreytarasevich@hotmail.com>
Date2021-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]


#158413

FromAndrey Tarasevich <andreytarasevich@hotmail.com>
Date2021-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]


#158416

Fromwij <wyniijj@gmail.com>
Date2021-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]


#158421

FromJames Kuyper <jameskuyper@alumni.caltech.edu>
Date2021-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