How union share the same memory

Thread Starter

mukesh1

Joined Mar 22, 2020
68
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
1586239955401.png
 

Ian Rogers

Joined Dec 12, 2012
1,136
The best way I describe the usefulness of a union is for accessing longwords easily

if you have a longword ( 4 bytes ) and an array of access[4] at the same address..

long = 0x12345678

access[0] = 0x12
access[1] = 0x34
access[2] = 0x56
access[3] = 0x78

Kinda like the basic equivalent of longword.LB etc..
Obviously a two 16 bit integer array can also be placed

union longword {
long a;​
int b[2];​
byte c[4];​
};

Any clearer?
 

xox

Joined Sep 8, 2017
838
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
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.
 

WBahn

Joined Mar 31, 2012
29,978
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
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).

What is likely confusing you is that you are thinking that all of the members can coexist in a union at the same time. They can't. If you store something in v.z, then whatever was stored in there for any of the other members is corrupted.

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.
 

Thread Starter

mukesh1

Joined Mar 22, 2020
68
Just for clarity... The structure:-
View attachment 203780
Code:
#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;
}
v.x = 4
v.x = 1
v.x = 4
v = 12


Code:
#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;
}
v.x = 4
v.x = 1
v.x = 4
v = 4

1586285898809.png

I didn't understand your diagram for union Can you describe it ? What is spare ?
 

WBahn

Joined Mar 31, 2012
29,978
"Spare" is just memory that is not being used for that member.

That diagram is assuming that an int is two bytes, which is hasn't been in a very long time for the overwhelming majority of compilers (there may well be some embedded compilers for which that is still the case). But we can use that for this without any problems.

So when you write to v.x, the two-byte integer value is put in the first two bytes of the union and the other two bytes aren't used (they are "spare").

Similarly, when you write a one-byte char to x.y, the remaining three bytes are unused.

In the case of your specific compiler, it is using all four bytes for both the int and the float, but only the first byte for the char.
 

djsfantasi

Joined Apr 11, 2010
9,156
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.
Code:
union bytemap {
    unsigned int myInt;
    char myByte[1];
}
You can retrieve the low byte of myInt by referencing myByte[1]. You can retrieve the high byte by referencing myByte[0].[/CODE]
 

xox

Joined Sep 8, 2017
838
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.
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));
}
 

WBahn

Joined Mar 31, 2012
29,978
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));
}
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).
 

xox

Joined Sep 8, 2017
838
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.
Code:
union bytemap {
    unsigned int myInt;
    char myByte[1];
}
You can retrieve the low byte of myInt by referencing myByte[1]. You can retrieve the high byte by referencing myByte[0].[/CODE]
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...
 

xox

Joined Sep 8, 2017
838
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).
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.
 

WBahn

Joined Mar 31, 2012
29,978
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.
Code:
union bytemap {
    unsigned int myInt;
    char myByte[1];
}
You can retrieve the low byte of myInt by referencing myByte[1]. You can retrieve the high byte by referencing myByte[0].[/CODE]
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.
 

WBahn

Joined Mar 31, 2012
29,978
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...
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.
 

xox

Joined Sep 8, 2017
838
Code:
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);
}
 

djsfantasi

Joined Apr 11, 2010
9,156
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.
I shoulda known better. ;)

I left out unsigned char and the -endian issue because for an introductory example, those points would have only confused the issue more.

But @WBahn is 100% correct. But neither point changes my example significantly.
 

nsaspook

Joined Aug 27, 2009
13,081
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.
“strong typing” just means pounding hard on the keyboard.
 
Top