The actual amount of memory allocated for a union ultimately depends on the largest possible representation, plus whatever padding (due to alignment or otherwise) the compiler decides to throw in there.The important difference between structures and unions is that in structures each member has it’s own memory whereas members in unions share the same memory.
I do not understand memory allocation for union How to draw the diagram to show memory allocation for union
What's drawing for following union ?Using drawings
#include <stdio.h>
struct example
{
int x;
char y;
float z;
}
int main()
{
struct example v;
v.x = 20;
v.y ='y';
v.z = 11.23;
return 0;
}
As the description states, all of the members share the same memory. So v.x, v.y, and v.z ALL start at the base address of the structure. The structure, as a whole, is probably 4 bytes long (it could be eight with some compilers).The important difference between structures and unions is that in structures each member has it’s own memory whereas members in unions share the same memory.
I do not understand memory allocation for union How to draw the diagram to show memory allocation for union
View attachment 203739
Just for clarity... The structure:-
View attachment 203780
#include <stdio.h>
struct example
{
int x;
char y;
float z;
};
int main()
{
struct example v;
v.x = 20;
v.y ='y';
v.z = 11.23;
printf("v.x = %d \n", sizeof(v.x));
printf("v.x = %d \n", sizeof (v.y));
printf("v.x = %d \n", sizeof(v.z));
printf("v = %d \n", sizeof(v));
return 0;
}
Like This
View attachment 203779
#include <stdio.h>
union example
{
int x;
char y;
float z;
};
int main()
{
union example v;
v.x = 20;
v.y ='y';
v.z = 11.23;
printf("v.x = %d \n", sizeof(v.x));
printf("v.x = %d \n", sizeof (v.y));
printf("v.x = %d \n", sizeof(v.z));
printf("v = %d \n", sizeof(v));
return 0;
}
union bytemap {
unsigned int myInt;
char myByte[1];
}
Common use case: simulating polymorphic behavior in C. You see this kind of thing in scripting engines.Unions don't see a lot of use, but there are a few things that they are useful for and that includes things related to system programming, and since C was invented to aid system programming (the Unix operating system, in particular), that is why it supports them.
#include "stdio.h"
enum
{
type_void,
type_integer,
type_real
};
typedef union
{
long integer;
double real;
}
blob;
typedef struct
{
int type;
blob value;
}
number;
number make_integer(long value)
{
number result;
result.type = type_integer;
result.value.integer = value;
return result;
}
number make_real(double value)
{
number result;
result.type = type_real;
result.value.real = value;
return result;
}
number make_void(void)
{
number result = { 0 };
return result;
}
void print_number(number data)
{
switch(data.type)
{
case type_real:
printf("real: %g\n", data.value.real); break;
case type_integer:
printf("integer: %ld\n", data.value.integer); break;
default:
puts("(void)");
}
}
int main()
{
print_number(make_real(1.234e-4));
print_number(make_void());
print_number(make_integer(5678));
}
That basically the same use that compilers make of it. You don't know what data type you are passing around, so you use a union that can hold any data type and let the passer and the receiver communicate the information about type through some side channel (which can be simply which function is being called).Common use case: simulating polymorphic behavior in C. You see this kind of thing in scripting engines.
Code:#include "stdio.h" enum { type_void, type_integer, type_real }; typedef union { long integer; double real; } blob; typedef struct { int type; blob value; } number; number make_integer(long value) { number result; result.type = type_integer; result.value.integer = value; return result; } number make_real(double value) { number result; result.type = type_real; result.value.real = value; return result; } number make_void(void) { number result = { 0 }; return result; } void print_number(number data) { switch(data.type) { case type_real: printf("real: %g\n", data.value.real); break; case type_integer: printf("integer: %ld\n", data.value.integer); break; default: puts("(void)"); } } int main() { print_number(make_real(1.234e-4)); print_number(make_void()); print_number(make_integer(5678)); }
You can't be sure of byte order though, you'd need to use some other method to detect that. That's one of the tricky things about unions. Very easy to wade into undefined behavior...A structure appends several variables into one entity to simplify processing and addressing. If there are ‘n’ variables in the structure, then the structure stores ‘n’ different values.
A union maps several different variables “on top” of one another. If there are ‘n’ different variables in a union, there is only one value, whatever is stored into any variable in the union.
I used the term “maps” purposely. One very application of unions, is to map the component portions of a variable to the whole value. Here is an trivial example.
You can retrieve the low byte of myInt by referencing myByte[1]. You can retrieve the high byte by referencing myByte[0].[/CODE]Code:union bytemap { unsigned int myInt; char myByte[1]; }
C++ supposedly solves this problem with the introduction of virtual functions, although at a cost which is arguably much higher than the (probably zero-overhead) C version.That basically the same use that compilers make of it. You don't know what data type you are passing around, so you use a union that can hold any data type and let the passer and the receiver communicate the information about type through some side channel (which can be simply which function is being called).
IF you are working on a little-endian machine.A structure appends several variables into one entity to simplify processing and addressing. If there are ‘n’ variables in the structure, then the structure stores ‘n’ different values.
A union maps several different variables “on top” of one another. If there are ‘n’ different variables in a union, there is only one value, whatever is stored into any variable in the union.
I used the term “maps” purposely. One very application of unions, is to map the component portions of a variable to the whole value. Here is an trivial example.
You can retrieve the low byte of myInt by referencing myByte[1]. You can retrieve the high byte by referencing myByte[0].[/CODE]Code:union bytemap { unsigned int myInt; char myByte[1]; }
Technically (I believe), unions are the only thing that prevent C from being a strongly typed language. But some disagree. There are differing opinions on what "strongly typed" means.You can't be sure of byte order though, you'd need to use some other method to detect that. That's one of the tricky things about unions. Very easy to wade into undefined behavior...
int little_endian_machine(void)
{
static int state, initialized = 0;
if(!initialized)
{
const unsigned long sample = 1;
state = (*((unsigned char*)&sample) == 1);
initialized = 1;
}
return state;
}
#include "stdio.h"
int main(void)
{
char* prefix = little_endian_machine() ? "little" : "big";
printf("Congratulations, you're running on a %s-endian machine!\n", prefix);
}
I shoulda known better.IF you are working on a little-endian machine.
In either case, you really should use an unsigned char. It's needlessly confusing to set myInt to 32799 and have the high byte be -113 and the low byte be -65.
Now, as an exercise once they are (or should be) comfortable with these concepts, that would be fair game.
Back when I was teaching C, this is one of the things I used unions for -- showing how you could get at the internal representation of something very easily. It's also good for showing cross-representation artifacts.
Something that any C programmer sees from time to time is something that looks like garbage. For instance,
int x;
x = 1000;
printf("%f\n", x);
because they printed an int as a double.
Since one of the things I always covered was the internal data representation of all the data types, including IEEE-754, I expected them to be able to determine what that would print out by hand. Using demo programs that used unions to tear apart the representation. It also make demoing little-endian a lot clearer (I thought). By using a file that has values stored in big endian, you can show the difference even on a little endian machine.
Some students found it fascinating, but most just complained.
“strong typing” just means pounding hard on the keyboard.Technically (I believe), unions are the only thing that prevent C from being a strongly typed language. But some disagree. There are differing opinions on what "strongly typed" means.
by Aaron Carman
by Duane Benson
by Jake Hertz