Confused on union vs structure

Thread Starter

@vajra

Joined May 2, 2018
145
I am confused on union vs structure in terms of memory location
Structure Program
Code:
#include<stdio.h>
struct s{ int x; int y;}a;
int main ()
{
    a.x = 1;
    a.y = 2;  
    printf ("%d ", a.x);
    printf ("%d ", a.y);
    return 0;
}
1 2
Union Program
Code:
#include<stdio.h>
union u{ int x; int y;}a;
int main ()
{
    a.x = 1;
    a.y = 2;  
    printf ("%d ", a.x);
    printf ("%d ", a.y);
    return 0;
}
2 2

What is meaning of union variables occupy the same memory, and structure variable occupy separate memory location
 
Last edited:

WBahn

Joined Mar 31, 2012
24,854
What do the results of running those two programs indicate about the two members of the union versus the struct?
 

Thread Starter

@vajra

Joined May 2, 2018
145
What do the results of running those two programs indicate about the two members of the union versus the struct?
Compiler allocate different memory location for structure and allocate same memory for union
Structure take 8 bytes and union take 4 bytes
Code:
#include<stdio.h>
struct s{ int x; int y;}a;
union u{ int x; int y;}b;
int main ()
{
    a.x = 1;
    a.y = 2;
    b.x = 3;
    b.y = 4;
    printf ("\n %d ", a.x);
    printf ("\n %d ", a.y); 
    printf ("\n %d ", b.x);
    printf ("\n %d ", b.y);
  
    printf ("\n %d ", &a.x);
    printf ("\n %d ", &a.y); 
    printf ("\n %d ", &b.x);
    printf ("\n %d ", &b.y);
  
    printf ("\n %d ", sizeof(a));
    printf ("\n %d ", sizeof(b));
      
    return 0;
}
1
2
4
4
4223088
4223092
4223096
4223096
8
4
 
Last edited:

dl324

Joined Mar 30, 2015
9,143
I don't understand why the result of print statement for b.x wasn't 3. That's what my first question ?
The largest element in a union determines the space the compiler will allocate. Because of that, you can only use one member of the union. You can use b.x or b.y, but not both at the same time because they use the same memory.
 

WBahn

Joined Mar 31, 2012
24,854
I don't understand why the result of print statement for b.x wasn't 3. That's what my first question ?
But you already answered it: "Compiler allocate different memory location for structure and allocate same memory for union "

Imagine you are using index cards for your variables. Each card can only have one number written on it at a time.

For the struct, you need two cards. One labeled 'x' and one labeled 'y'.
If you write to 'x', you erase the number on the 'x' card and write the new number.
If you read from 'x' you read the number on the 'x' card.
If you write to 'y', you erase the number on the 'y' card and write the new number.
If you read from 'y' you read the number on the 'y' card.

For the union, you just need one card, labeled 'x'/'y'.
If you write to 'x', you erase the number on the 'x'/'y' card and write the new number.
If you read from 'x' you read the number on the 'x'/'y' card.
If you write to 'y', you erase the number on the 'x'/'y' card and write the new number.
If you read from 'y' you read the number on the 'x'/'y' card.
 

Thread Starter

@vajra

Joined May 2, 2018
145
You can use b.x or b.y, but not both at the same time because they use the same memory.
But experiment say your statement is wrong
Code:
#include<stdio.h>

union u{ int x; int y; int z;}b;
int main ()
{
    b.x = 3;
    b.y = 2;
    b.z = 1;

    printf ("\n %d ", b.x);
    printf ("\n %d ", b.y);
    printf ("\n %d ", b.z);

    printf ("\n %d ", &b.x);
    printf ("\n %d ", &b.y);
    printf ("\n %d ", &b.z);

    printf ("\n %d ", sizeof(b)); 
    return 0;
}
Compiler allocate only one memory location and union store only last member
1
1
1
4223088
4223088
4223088
4

Code:
#include<stdio.h>

union u{ int x; int y; int z;}b;
int main ()
{

    b.x = 1;
    b.y = 2;
    b.z = 3;

    printf ("\n %d ", b.x);
    printf ("\n %d ", b.y);
    printf ("\n %d ", b.z);

   
    printf ("\n %d ", &b.x);
    printf ("\n %d ", &b.y);
    printf ("\n %d ", &b.z);

    printf ("\n %d ", sizeof(b));
   
    return 0;
}
3
3
3
4223088
4223088
4223088
4
 
Last edited:

Thread Starter

@vajra

Joined May 2, 2018
145
But you already answered it: "Compiler allocate different memory location for structure and allocate same memory for union "
Imagine you are using index cards for your variables. Each card can only have one number written on it at a time.
I do not understand purpose of union in c programming. Union can store only one member I don't think it's useful

Can you please tell me when they can more useful in program
 

nsaspook

Joined Aug 27, 2009
6,500
A real-world code fragment example of using a union in C to convert from a 8-bit SPI binary stream of data to a easily used and accessed C structure.
You can use the same memory space in several different ways, each way translates the addressing and data needs of the individual function.

C:
/* for 24-bit transmit and extra status data  in 32 bits of total data space*/
typedef struct A_data {
    uint32_t dummy12 : 12; // dummy space for adc data
    uint32_t nullbits : 2;
    uint32_t index : 3; //adc channel select
    uint32_t single_diff : 1;
    uint32_t start_bit : 1;
    uint32_t dummy8 : 8;
    uint32_t finish : 1;
    uint32_t in_progress : 1;
} A_data;

/* used to hold 24-bit adc buffer, index and control bits */
union adc_buf_type {
    uint32_t ld; // one 32-bit variable
    uint8_t bd[4]; // 4 8-bit variables
    struct A_data map; // one 32-bit structure
};

typedef struct {
    union adc_buf_type mcp3208_cmd;
    uint16_t potValue;
    uint8_t chan;
} ADC_DATA;

ADC_DATA adcData; // create the program variable

void ADC_Init()
{
    adcData.mcp3208_cmd.ld = 0; // clear the command word 32-bit word in the union clears all structure data
    adcData.chan = 0;
    adcData.mcp3208_cmd.map.start_bit = 1;
    adcData.mcp3208_cmd.map.single_diff = 1;
    adcData.mcp3208_cmd.map.index = 0; // channel
    appData.ADCcalFlag = true;
    SPI_CS0 = 1;
}

//State machine for restarting ADC and taking new readings from pot
//Returns true when SPI data has been returned from the mpc3208; false otherwise

bool ADC_Tasks(void)
{
    static uint8_t count = 0;

    /* send the command sequence to the adc */
    if (!adcData.mcp3208_cmd.map.in_progress) {
        adcData.mcp3208_cmd.map.in_progress = true;
        adcData.mcp3208_cmd.map.finish = false;
        count = 0;
        if (!SPI_IsTxData()) {
            adcData.mcp3208_cmd.map.single_diff = 1;
            adcData.mcp3208_cmd.map.index = adcData.chan;
            SPI_ClearBufs(); // dump the spi buffers
            // send the structure as a sequence of 8-bit bytes
            SPI_WriteTxBuffer(adcData.mcp3208_cmd.bd[2]);
            SPI_WriteTxBuffer(adcData.mcp3208_cmd.bd[1]);
            SPI_WriteTxBuffer(adcData.mcp3208_cmd.bd[0]);
            SPI_CS0 = 0; // select the ADC
            SPI_Speed(0);
            SPI_TxStart();
        }
        return false;
    }

    /* read the returned spi data from the buffer and format it */
    if (adcData.mcp3208_cmd.map.in_progress) {
        while (SPI_IsNewRxData()) {
            switch (count) {
            case 1:
                adcData.potValue = (SPI_ReadRxBuffer()&0x0f) << 8;
                break;
            case 2:
                adcData.potValue += SPI_ReadRxBuffer();
                adcData.mcp3208_cmd.map.finish = true;
                break;
            default:
                SPI_ReadRxBuffer(); // eat extra bytes
                break;
            }
            count++;
        }
    }

    /* cleanup for next time */
    if (adcData.mcp3208_cmd.map.finish) {
        adcData.mcp3208_cmd.map.in_progress = false;
        appData.accumReady = true;
        return true;
    }

    return false;
}
 

dl324

Joined Mar 30, 2015
9,143
But experiment say your statement is wrong
Check again. It's you who is mistaken.

In this example, you set b.x = 3 and then b.y = 2 and then set b.z to 1. When you print the three variables the result is wrong. You get 1 printed 3 times because your last assignment to the union b is 1.
Code:
#include<stdio.h>

union u{ int x; int y; int z;}b;
int main ()
{
    b.x = 3;
    b.y = 2;
    b.z = 1;

    printf ("\n %d ", b.x);
    printf ("\n %d ", b.y);
    printf ("\n %d ", b.z);

    printf ("\n %d ", &b.x);
    printf ("\n %d ", &b.y);
    printf ("\n %d ", &b.z);

    printf ("\n %d ", sizeof(b));
    return 0;
}
Compiler allocate only one memory location and union store only last member
1
1
1
4223088
4223088
4223088
4
 

BobaMosfet

Joined Jul 1, 2009
836
I am confused on union vs structure in terms of memory location
Structure Program
Code:
#include<stdio.h>
struct s{ int x; int y;}a;
int main ()
{
    a.x = 1;
    a.y = 2; 
    printf ("%d ", a.x);
    printf ("%d ", a.y);
    return 0;
}
1 2
Union Program
Code:
#include<stdio.h>
union u{ int x; int y;}a;
int main ()
{
    a.x = 1;
    a.y = 2; 
    printf ("%d ", a.x);
    printf ("%d ", a.y);
    return 0;
}
2 2

What is meaning of union variables occupy the same memory, and structure variable occupy separate memory location

A union and a structure are not the same thing.

A structure is a grouping of several variables into an object that has a single address, with each variable having it's own memory within the object. The compiler accesses each variable by utilizing the object address and an offset.

On the other hand, a union makes each variable in the grouping share the same memory location, and the only difference between them is size (based on which variable you're addressing).

Struct:
Code:
typedef struct
   {
   char   a;
   char   b;
   short   c;
   }variables3;

variables3 myVar;

myVar.a = 0x41;
myVar.b = 0x42;
myVar.c = 12924;
Now, if we view the actual memory for the structure, it's going to look like this:
Code:
ADDRESS     |  MEMORY                    | ASCII Representation
------------+----------------------------+-----------------
0x0000 0000 | 41 42 32 7C 00 00 00 01 14 | AB2|.....
Now with a Union:
Code:
typedef union
   {
   char   a;
   char   b;
   short   c;
   }variables3;

variables3 myVar;

myVar.a = 0x41;
myVar.b = 0x42;
myVar.c = 12924;
Now, if we view the actual memory for the union, it's going to look like this:
Code:
ADDRESS     |  MEMORY                    | ASCII Representation
------------+----------------------------+-----------------
0x0000 0000 | 32 7C 00 00 00 00 00 01 14 | 2|.......
Do you see how in the union, each time you assigned a value to a variable, it reused the SAME memory (overwriting the previous declaration)? 0x327C = 12924 in decimal.

The reason unions exist is so that you can treat the same data with different types, depending on the needs of your program. You might have something that enters 4 8-bit values as a 4-byte array within the first variable of a union, but another aspect of your program wants to refer to it as a 4-byte address (long). This makes it easier to do so, and does not use casting, or other mechanisms.

You can unionize entire structures so that different parts of a program are aware only of the data in one structure, but another part of the program might see additional fields because the second structure in the union has more fields with more information. This can be a really powerful thing in queue techniques.
 

WBahn

Joined Mar 31, 2012
24,854
I do not understand purpose of union in c programming. Union can store only one member I don't think it's useful

Can you please tell me when they can more useful in program
There are a number of places where unions are useful (despite the bad things that can happen very quickly if they are misused).

In embedded systems you often have extreme memory limitations. If you know that you have several variables that are only ever needed one at a time with no overlap, then you can put them into a union.

Unions are also very convenient when you don't know ahead of time what the type is. You can put the data into a union and track the type separately.
 

nsaspook

Joined Aug 27, 2009
6,500
Another thing that unions/structures do in C is to provide a structured programming namespace (types, functions, variables, etc) that with the proper IDE allows for drop down selection and editing of source code to the needed software component without keeping the entire namespace in your head. This is a OOP feature that programmers love with as it allows for you to write source in a less error prone fashion when the related data is formatted into related objects the editor tracks. Languages like C++ and most OOP languages have a extensive namespace capabilities for single source file use but it's possible in plain C with proper module headers, modular file discipline and programming practice.

https://ejrh.wordpress.com/2012/01/24/namespaces-in-c/
C does not have an operator “::”. But it does have “.”: this is used to access a field in a struct. If we define a suitable struct, and make an instance of it with appropriate initial values, we can use it as a namespace. The namespace becomes reified (made real) in the sense that it is no longer a convention on the first few letters in each name, but is now a separate symbol in the program.
 

Ian Rogers

Joined Dec 12, 2012
666
If it helps.... I use unions for serialization.. Assume I have 4 sensors each a long

union {
long value[4]; // storage for sensors
char serialization[16]; //char array ready for serial port!!
} sensor;

Just write your sensor data to the long array, then send it out byte by byte to an external device.
 
Top