Reputation: 4433
If a union in C is used to for example pack a variable into a byte array as in the type described below:
typedef union
{
uint16_t integer;
byte binary[4];
} binaryInteger;
When is the actual union performed? Is it when the variables are assigned to any of the parts of the union. Or is it when that part is accessed?
Is the current or previous assignments (Depending on when it is performed) accessible in any way without causing the union to execute?
Upvotes: 2
Views: 164
Reputation: 726969
In C and C++ unions are passive, so technically they are never "performed". They tell the compiler how you want to do the memory layout for the type controlled by the union.
The compiler computes, at compile time, the size of the union
(which is at least the size of its largest member and is more if padding is needed for alignment). Then the placement of data in memory happens as you do the assignments to members of your union
.
Upvotes: 8
Reputation: 8843
Your question can't really be answered because Unions are not actually "performed".
When you write a program in machine language, all you have is a bunch of bytes, and you tell the computer what to do with these bytes. Which can be "treat the 4 bytes following this address as a signed integer and add 5 to them" or whatever.
Higher-level languages like C keep information around about the data type that a certain bunch of bytes has to make things easier for you (i.e. so you can just say myVar = 5
instead of having to say something like assign4ByteSignedInteger(myVar,5)
). When C is compiled into actual machine language, it will automatically pick the right machine instruction for the type you gave e.g. to a local variable.
Usually, that's good, you want that convenience. Unions are a bit of syntactic sugar that lets you break this "type-safety-net" selectively in cases where you know that a certain bunch of bytes has two uses. Unions are for the programmer, at design-time. To the computer they might as well not exist.
So Unions aren't operations, they are simply type directives. Just as you can't say "when is an int executed", you can't say the same about Unions.
Upvotes: 4
Reputation: 129504
Technically, the compiler will just put the two different fields (in this case) at the same address. The largest member (in this case the array of 4 bytes) determines the overall size of the union
.
Now, there is also a bunch of complicated rules about unions and how you can access the fields, so whilst in this case, binary
being a variant of char
, it should be fine to stuff a couple of bytes into binary[0]
and binary[1]
, if we for example use:
union x { int a; float b; };
using x.a = 0x3f800000;
does not guarantee that cout << x.b << endl;
prints 1.0 or something like that. Aside from array of char
(can be unsigned), all other types require that you access the same field that you originally stored, or it's undefined behaviour. So, in this situation, a union
can only be used for "storing different types of data", but you do need to somehow KNOW which kind of data it is for each instance of the union
. It is still a powerful thing to save space in situations where you have a structure that may have two different representations in some way.
Note that undefined behaviour is bad, since it MAY appear to work, then you change compiler, change compiler settings, change the code itself, or something like that, and suddenly, the code behaves differently.
Upvotes: 1
Reputation: 91119
I am not clear what you mean saying to execute the union.
Whenever you put data into one of the fields, the data is put into memory. And then, accessing another field, you read the same data with the respective field's interpretation.
For example, your union in the question takes 4 bytes. The first 2 bytes are as well mapped to the integer.
+----+----+----+----+
| | | | | raw bytes
+----+----+----+----+
| | | integer
+----+----+
If you put the value of 0x1234
into the integer, the first two bytes of the array are set to 0x12
and 0x34
, respectively. (The order depends on the endianness of the system.)
OTOH, if you set bytes[0]
and/or bytes[1]
, you immediately affect the value of integer
.
Upvotes: 7