Home > Net >  Active member of an union after assignment
Active member of an union after assignment

Time:09-01

Suppose sizeof( int ) == sizeof( float ), and I have the following code snippet:

union U{
    int i;
    float f;
};

U u1, u2;
u1.i = 1;    //i is the active member of u1
u2.f = 1.0f; //f is the active member of u2

u1 = u2;

My questions:

  1. Does it have a defined behaviour? If not why?
  2. What is the active member of u1 after the assignment and why?
  3. Which member of u1 can be read from after the assignment without causing an UB and why?

CodePudding user response:

My questions:

  1. Does it have a defined behaviour? If not why?

It has defined behaviour. The assignment copy the value of u2 and for me the value of an union is a designation of the active member (although that part is not represented and so can't be examined but it determines what is UB and what is not) and the value of the active member if there is one.

  1. What is the active member of u1 after the assignment and why?

f, see above.

Which member of u1 can be read from after the assignment without causing an UB and why?

f. In general, only the active member of an union can be read without UB in C . There is a special rule for union of structs where those struct have a common initial sequence. Note: C is more relaxed and makes implementation defined (and perhaps completely defined) some cases which are undefined in C and I may have missed some changes in C to make it more compatible with C.


If someone want to look up the standard, I suggest starting with class.copy.assign/13.

CodePudding user response:

Edit: Sorry, this is an answer for C, not C . @AProgrammer posted a nice answer. I'll let the community decide whether this should stay here.

  1. Technically, it is defined behaviour. This is just the question of how you represent a chunk of memory. I encourage you to play with this float calculator. It might help you to understand what happens there. Row binary representation is the memory those int and float share, row Decimal representation how the memory is represented as float, and if you put the row Hexadecimal representation into here, you get how it is represented as an integer. !!! I'm not saying it's good practice, it is just equivalent to using reinterpret_cast<int&&>(1.0f) in C . (assuming sizeof(int) == sizeof(float) ) !!!
  2. I think that you are a bit confused about unions. There is no such thing as an active member in C. All of them are accessible at any given time and one could say that they provide different "views" of the same memory.
  3. Both, but you have to expect that if you store an integer -15626 then you will get NaN float value and other "funny" things that IEEE-754 defines.

CodePudding user response:

#include <bits/stdc  .h>
#include <iostream>
using namespace std;
union U
{
        int i;
        char a1[4];
        float f;
};
int main()
{
        U u1, u2;
        u1.i = 1;       // i is the active member of u1
        u2.f = 1.0f;    // f is the active member of u2
        bitset<32> b(u1.i);
        cout << "u1.i:" << b << endl;
        cout << "Original value u1.i: " << u1.i << "\n";
        cout << "Original value u1.f: " << (float)u1.f << "\n";
        u1 = u2;
        b=u1.i;
        cout << "Modified value u1.i: " << u1.i << "\n";
        cout << "Modified value u1.f: " << (float)u1.f << "\n";
        cout << "u1 = u2 u1.i :" << b << endl;
        b=u1.f;
        cout << "u1 = u2 u1.f :" << b << endl;
        return 0;
}
/*
$ g   -Wall -g 73555327.cpp -o ./a.out
$ ./a.out
u1.i:00000000000000000000000000000001
Original value u1.i: 1
Original value u1.f: 1.4013e-45
Modified value u1.i: 1065353216
Modified value u1.f: 1
u1 = u2 u1.i :00111111100000000000000000000000
u1 = u2 u1.f :00000000000000000000000000000001
$ # READ SIGN EXPONENT AND MANTISSA USING float/double
$ # EG URL: https://www.infoworld.com/article/2077257/floating-point-arithmetic.html
*/
  • Related