how union is different then structure in context of memory

Discussion in 'Programmer's Corner' started by anukalp, Oct 10, 2018.

  1. anukalp

    Thread Starter Member

    Jul 28, 2018
    88
    0
    Hello

    I'm trying to understand how union is different then structure in context of memory in c language

    Example for structure
    Code (C):
    1. struct student{
    2.     int roll_number;
    3.     float mark ;
    4. }record;
    Example for union
    Code (C):
    1. union student{
    2.     int roll_number;
    3.     float mark ;
    4. }record;
    Can anyone help me to understand how union is different then structure in context of memory in c language ?
     
  2. MrSoftware

    Well-Known Member

    Oct 29, 2013
    1,054
    296
    In a structure, each of the elements gets their own memory. So your record.roll_number and record.mark are separate. In a union, all elements share the same memory. So in case of your union, your record.roll_number and record.mark actually point to the same starting memory address. With the union, if you assign record.roll_number = 1, then assign record.mark = 2.5, the assignment of record.mark will overwrite the value in record.roll_number.

    Write your program using each, open the memory watch in your debugger and watch the memory change as you step through the code.
     
    Last edited: Oct 10, 2018
    anukalp and Kjeldgaard like this.
  3. anukalp

    Thread Starter Member

    Jul 28, 2018
    88
    0
    I didn't understand
    consider example
    Code (C):
    1. union student
    2. {
    3.     int roll_number;
    4.     float mark ;
    5. }record;
    memory space
    0001
    0002
    0003
    0004
    .......

    0010

    how the union will allocate memory space ?

    I have MinGW and it works great. I just don't know how to use the debugger. I have looked for documentation on this and found nothing.
     
    Last edited: Oct 10, 2018
  4. WBahn

    Moderator

    Mar 31, 2012
    22,988
    6,883
    As MrSoftware said, a union will lay the elements over each other in the same memory. If you use a structure and your int data type is four bytes (and float is pretty much always four bytes), then the structure will require eight bytes (minimum) and both members have their own memory within that space. If you use a union, then the entire object will probably require just four bytes because both data members are assigned to the same four bytes of memory, meaning that you can only use one at a type.

    Unions are useful when you need to store different types of data at different times, but only one type at any given time. They are also very dangerous from a bug and security standpoint.
     
    simozz and anukalp like this.
  5. dl324

    AAC Fanatic!

    Mar 30, 2015
    7,091
    1,629
    The compiler will allocate memory sufficient to store the largest element.
     
  6. atferrari

    AAC Fanatic!

    Jan 6, 2004
    3,014
    1,118
    Not C conversant myself. Is the largest element defined at compiling or running time?
     
  7. dl324

    AAC Fanatic!

    Mar 30, 2015
    7,091
    1,629
    At compile time. If you have pointers that have their memory allocated at run time, only the storage for the pointer is allocated at compile time.
     
  8. anukalp

    Thread Starter Member

    Jul 28, 2018
    88
    0
    assume int data type take four bytes and float data type take four bytes

    int roll_number = 0010;
    float mark = 35.50

    then the structure will require eight bytes and both members have their own memory within that eight bytes space.

    What do you mean by this line ?
     
  9. dl324

    AAC Fanatic!

    Mar 30, 2015
    7,091
    1,629
    From K&R C Programming Language, 2nd Edition:
    upload_2018-10-10_8-34-40.png
     
  10. MrSoftware

    Well-Known Member

    Oct 29, 2013
    1,054
    296
    You really need to figure out the debugger, learning C without a debugger is going to be very painful. What platform are you on? If you have Windows available, download the free version of Microsoft Visual Studio. The Visual Studio debugger is fantastic and makes watching memory very easy. Else you can use gdb on the command line, or check out Eclipse which I believe will give you a GUI on top of gdb; it's not going to be as nice as Visual Studio, but it's better than nothing.

    If you want to do it the painful way with some printf's; in code, declare the struct then print the address of each of the members in the struct. Then declare the union and print the address of each of the members of the union. With the struct every element will have a different address. In the union the addresses will all match.

    Think of your union like this:
    1. union student
    2. {
    3. int roll_number;
    4. float mark ;
    5. }record;

    This is more or less the same as doing this (pseudo code):

    byte memory_space[4];
    int *roll_number = (int*)&memory_space[0];
    float *mark = (float*)&memory_space[0];
     
    Last edited: Oct 10, 2018
    anukalp likes this.
  11. MrSoftware

    Well-Known Member

    Oct 29, 2013
    1,054
    296
    I stumbled on this, which is too cool for words. It uses gdb for debugging:

    https://www.onlinegdb.com/online_c_compiler

    Code (Text):
    1. #include <stdio.h>
    2.  
    3. struct{
    4.     int my_int;
    5.     float my_float;
    6. }mystruct;
    7.  
    8. union{
    9.     int my_int;
    10.     float my_float;
    11. }myunion;
    12.  
    13.  
    14. int
    15. main ()
    16. {
    17.   printf("mystruct.my_int:  0x%d\n", &mystruct.my_int);
    18.   printf("mystruct.my_float:  0x%d\n", &mystruct.my_float);
    19.  
    20.   printf("myunion.my_int:  0x%d\n", &myunion.my_int);
    21.   printf("myunion.my_float:  0x%d\n", &myunion.my_float);
    22.  
    23.   return 0;
    24. }
    25.  
    upload_2018-10-10_11-56-41.png

    upload_2018-10-10_11-56-57.png


    The GDB output is even better, it tells you explicitly that the float is 4 byte past the int in the struct, but the same address in the union:

    upload_2018-10-10_12-1-0.png
     
    anukalp likes this.
  12. WBahn

    Moderator

    Mar 31, 2012
    22,988
    6,883
    Simple -- if you use the four bytes to store an int, you can't ALSO use it to store a float AT THE SAME TIME. Your program has to chose -- but it can change that choice as often as needed.

    So initially I might store an int in it by saying

    student.roll_number = 10;

    That means that the pattern of thirty-two bits stored in those four memory locations is consistent with a four-byte two's complement integer.

    But at some later type you might execute the statement

    student.mark = 35.50;

    and now the pattern of thirty-two bits stored in those four memory locations is consistent with a four-byte IEEE-754 single-precision floating point number.

    If you now try to do something like:

    roll_total = student.roll_number;

    you will get an incorrect result because the statement will interpret those 32-bits as a two's complement integer.
     
    anukalp likes this.
Loading...