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 11 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 2 of 2 — ← Prev page 1 [2]


#158478

FromTim Rentsch <tr.17687@z991.linuxsc.com>
Date2021-01-20 05:56 -0800
Message-ID<86turbogog.fsf@linuxsc.com>
In reply to#158413
Andrey Tarasevich <andreytarasevich@hotmail.com> writes:

[context: does the following code have undefined behavior?

        union {
          uint16_t u16;
          uint8_t  u8[2];
          float    flt;
        } u;
        
        void t() {
          u.u16=0;
        
          assert(u.u8[0]==0);
          assert(u.u8[1]==0);
        
        };

(end context)]

> [In C] there's no immediate UB when reading `u8`.  In general
> case the potential for UB is still there [because of trap
> representations], 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.)

All of the exact-width integer types [u]intN_t, including uint8_t,
cannot have trap representations.  The C standard doesn't say this
directly, but it follows pretty immediately from the properties of
exact-width integer types and from the definitions of object
representation and trap representation.  (For signed exact-width
types intN_t, section 7.20.2.1 provides a crucial piece of that
deduction, which is easy to miss if one doesn't know to look for
it.)

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


#158493

FromAndrey Tarasevich <andreytarasevich@hotmail.com>
Date2021-01-20 09:52 -0800
Message-ID<ru9qk5$i7m$1@dont-email.me>
In reply to#158478
On 1/20/2021 5:56 AM, Tim Rentsch wrote:
 >
 > All of the exact-width integer types [u]intN_t, including uint8_t,
 > cannot have trap representations.  The C standard doesn't say this
 > directly, but it follows pretty immediately from the properties of
 > exact-width integer types and from the definitions of object
 > representation and trap representation.  (For signed exact-width
 > types intN_t, section 7.20.2.1 provides a crucial piece of that
 > deduction, which is easy to miss if one doesn't know to look for
 > it.)
 >

Yes, I can see that now. 7.20.2.1 says that all combinations of 
value-forming bits are "taken" to represent valid values, and 7.20.1.1 
says that there are no padding bits in these types.

-- 
Best regards,
Andrey Tarasevich

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


#158479

FromTim Rentsch <tr.17687@z991.linuxsc.com>
Date2021-01-20 06:09 -0800
Message-ID<86pn1zog3l.fsf@linuxsc.com>
In reply to#158412
Andrey Tarasevich <andreytarasevich@hotmail.com> writes:

> 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.
>
> [Briefly, C defines the behavior, C++ makes the behavior undefined
>  in all cases.]
>
> 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.

It is exactly one of the uses that unions are for.

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


#158496

FromBonita Montero <Bonita.Montero@gmail.com>
Date2021-01-20 19:41 +0100
Message-ID<ru9tga$7i8$1@dont-email.me>
In reply to#158479
>> 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.

> It is exactly one of the uses that unions are for.

Yes, it's the only way to safely circumvent the strict aliasing rule.

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


#158497

Fromscott@slp53.sl.home (Scott Lurndal)
Date2021-01-20 18:49 +0000
Message-ID<gX_NH.14188$PB3.9015@fx18.iad>
In reply to#158496
Bonita Montero <Bonita.Montero@gmail.com> schrieb:
>>> 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.
>
>> It is exactly one of the uses that unions are for.
>
>Yes, it's the only way to safely circumvent the strict aliasing rule.

-fno-strict-aliasing

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


#158499

FromBonita Montero <Bonita.Montero@gmail.com>
Date2021-01-20 20:09 +0100
Message-ID<ru9v65$kc4$1@dont-email.me>
In reply to#158497
>>> It is exactly one of the uses that unions are for.

>> Yes, it's the only way to safely circumvent the strict aliasing rule.

> -fno-strict-aliasing

-fno-strict-aliasing doesn't make casted aliasing valid,
it only prevents compiler-warnings.

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


#158501

Fromscott@slp53.sl.home (Scott Lurndal)
Date2021-01-20 19:25 +0000
Message-ID<Ms%NH.27753$MW1.15087@fx20.iad>
In reply to#158499
Bonita Montero <Bonita.Montero@gmail.com> writes:
>>>> It is exactly one of the uses that unions are for.
>
>>> Yes, it's the only way to safely circumvent the strict aliasing rule.
>
>> -fno-strict-aliasing
>
>-fno-strict-aliasing doesn't make casted aliasing valid,
>it only prevents compiler-warnings.

Wrong. It instructs the compiler to generate code assuming that
anything can be aliased.

You've confused it with -Wstrict-aliasing=n.

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


#158502

FromDavid Brown <david.brown@hesbynett.no>
Date2021-01-20 20:29 +0100
Message-ID<rua0b6$t1s$1@dont-email.me>
In reply to#158499
On 20/01/2021 20:09, Bonita Montero wrote:
>>>> It is exactly one of the uses that unions are for.
> 
>>> Yes, it's the only way to safely circumvent the strict aliasing rule.
> 
>> -fno-strict-aliasing
> 
> -fno-strict-aliasing doesn't make casted aliasing valid,
> it only prevents compiler-warnings.
> 

No, it makes them valid - it changes the semantics of the language (C or
C++) to remove the "strict aliasing rule".  (There is no such single
rule in the standards - but it's a convenient summary of the actual rules.)

If you just want to hide the warnings (which would be a ridiculous thing
to do), use "-Wno-strict-aliasing".

Other than that, the common and definitely safe way to circumvent strict
aliasing is to use memcpy.


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


#158504

FromAndrey Tarasevich <andreytarasevich@hotmail.com>
Date2021-01-20 11:36 -0800
Message-ID<rua0nl$unt$1@dont-email.me>
In reply to#158496
On 1/20/2021 10:41 AM, Bonita Montero wrote:
>>> 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.
> 
>> It is exactly one of the uses that unions are for.
> 
> Yes, it's the only way to safely circumvent the strict aliasing rule.
> 

Not really the only way. A simple cast-based re-interpretation as an 
array of [signed/unsigned] char is not a violation of strict aliasing rules.

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


#158417

FromJames Kuyper <jameskuyper@alumni.caltech.edu>
Date2021-01-17 12:14 -0500
Message-ID<ru1ra3$d9s$1@dont-email.me>
In reply to#158407
On 1/17/21 9: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];

uint16 and uint8 are not standard-defined types. I didn't notice that
before, I assumed in my previous message that you were actually using
uint16_t and uint8_t, which are standard-defined. I'll continue that
assumption in this message.

>  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.

My previous message explained why you can read u8 or u16 in C. However,
you can't read flt.

On most implementations, float is a 32-bit type, usually IEEE/IEC
single-precision floating point. The standard doesn't specify a minimum
size for the type, but it does impose requirements on its
representations, and if I've calculated correctly, the minimum size
format that can meet those requirements takes up at least 25 bits.

An implementation for which uint8 is supported must have CHAR_BITS == 8,
so sizeof(float) >= 4.

Therefore, after you've set both elements of u8 to 0, there's at least 9
bits used by flt, and more likely 16 of them, that are still
uninitialized. That means you can't guarantee that it's a valid
representation. In particular, it's entirely possible for it to be a
signaling NaN, which means that any attempt to read it could cause your
program to abort.

> What does UB really mean in this situation?

The behavior is actually implementation-defined, not UB, though reading
flt could result in UB if it contains a trap representation (which is
not permitted for uint16.

Undefined Behavior, regardless of it's cause, always means
"behavior, upon use of a nonportable or erroneous program construct or
of erroneous data, for which this International Standard imposes no
requirements" (3.4.3p1).
Note that "undefined behavior" is NOT defined as "behavior which is not
defined". If the C standard doesn't define the behavior, but some other
document (such as the POSIX standard or your compiler's documentation)
does define the behavior, it still qualifies as undefined behavior as
far as the C standard is concerned.

The standard has a note which clarifies how thoroughly "no requirements"
applies: "Possible undefined behavior ranges from ignoring the situation
completely with unpredictable results, to behaving during translation or
program execution in a documented manner characteristic of the
environment (with or without the issuance of a diagnostic message), to
terminating a translation or execution (with the issuance of a
diagnostic message."

It might be impossible for your computer to self-destruct as a result of
executing code with undefined behavior, but not because of anything it
says in the C standard prohibiting that result.

Note that perhaps the single most dangerous way your program might
behave, is precisely the way you erroneously thought it was required to
behave. As a result, you won't notice that your expectations were incorrect.

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


#158418

FromBen Bacarisse <ben.usenet@bsb.me.uk>
Date2021-01-17 17:17 +0000
Message-ID<87wnwb7aah.fsf@bsb.me.uk>
In reply to#158407
wij <wyniijj@gmail.com> writes:

> 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?

Yes, it's fine.  Reading from a member that was not the last one
assigned to simply reinterprets the bits.  This has been made explicit
in recent standards (since C99) but the general opinion is that this is
what was always intended, since the clarification is in a footnote.

Of course, problems can occur if the value that results from this
reinterpretation is a trap representation, nut you are unlikely to come
across that situation and, anyway, it can't happen with uint8.

-- 
Ben.

[toc] | [prev] | [standalone]


Page 2 of 2 — ← Prev page 1 [2]

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


csiph-web