Thread: Unioning structs of different sizes?

  1. #1
    Registered User
    Join Date
    Nov 2008
    Posts
    127

    Unioning structs of different sizes?

    Is it safe to do something like
    Code:
    typedef union
    {
        struct
        {
              int a;
              int b;
              int c;
              int d;
        } val1;
    
        struct
        {
              int e;
              int f;
        } val2;
    }my_u;
    When I refer to the val2 field in the union, I only care about accessing a and b. Do I need to add the padding to val2?

  2. #2
    Algorithm Dissector iMalc's Avatar
    Join Date
    Dec 2005
    Location
    New Zealand
    Posts
    6,318
    Nope.
    Of course I assume you mean e and f, not a and b.
    My homepage
    Advice: Take only as directed - If symptoms persist, please see your debugger

    Linus Torvalds: "But it clearly is the only right way. The fact that everybody else does it some other way only means that they are wrong"

  3. #3
    Registered User
    Join Date
    Nov 2008
    Posts
    127
    Quote Originally Posted by iMalc View Post
    Nope.
    Damn, that would have made things easy.

    Quote Originally Posted by iMalc View Post
    Of course I assume you mean e and f, not a and b.
    Sort of. I want to access a and b via e and f.

  4. #4
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,613
    Wait a minute, I think you misunderstand. You can pretty much union anything, and in this case there shouldn't be any alignment issues.

  5. #5
    Registered User antred's Avatar
    Join Date
    Apr 2012
    Location
    Germany
    Posts
    257
    Quote Originally Posted by whiteflags View Post
    Wait a minute, I think you misunderstand. You can pretty much union anything, and in this case there shouldn't be any alignment issues.
    Yeah, when iMalc said "nope", he meant that no, you don't have to worry about adding any padding and yes, what you want to do is fine.

  6. #6
    Registered User
    Join Date
    Nov 2008
    Posts
    127
    Thanks for the clarification. I've never done a union that had fields of different sizes. I always assumed that each field in a union had to be the same size.

  7. #7
    [](){}(); manasij7479's Avatar
    Join Date
    Feb 2011
    Location
    *nullptr
    Posts
    2,657
    Quote Originally Posted by homer_3 View Post
    Thanks for the clarification. I've never done a union that had fields of different sizes. I always assumed that each field in a union had to be the same size.
    Then what would be the point of unions? Everyone would just use casts to get the same thing done.

  8. #8
    Registered User
    Join Date
    Nov 2008
    Posts
    127
    Quote Originally Posted by manasij7479 View Post
    Then what would be the point of unions? Everyone would just use casts to get the same thing done.
    What's the point of C++? Just use assembly. Oh yea, convenience.

  9. #9
    [](){}(); manasij7479's Avatar
    Join Date
    Feb 2011
    Location
    *nullptr
    Posts
    2,657
    Quote Originally Posted by homer_3 View Post
    What's the point of C++? Just use assembly. Oh yea, convenience.
    You missed my point.
    If unions only allowed members of same size, it would be much more convenient to just use casts.
    Or do you find verbose stuff more convenient?

  10. #10
    Registered User antred's Avatar
    Join Date
    Apr 2012
    Location
    Germany
    Posts
    257
    Quote Originally Posted by manasij7479 View Post
    Then what would be the point of unions? Everyone would just use casts to get the same thing done.
    If you were thinking of using unions as a convenient alternative to reinterpret_cast, like so:

    Code:
    union Foo
    {
        int intVal;
        float floatVal;
    };
    
    Foo bar;
    bar.intVal = 0x00ABCDEF;
    
    std::cout << "as float: " << bar.floatVal;
    be warned that code like this should be avoided. The standard states that reading from any union member other than the last one written to results in undefined behavior. While in practice this will usually work and yield the expected results, there's just no guarantee and you may one day run into a compiler where this kind of code breaks.

  11. #11
    [](){}(); manasij7479's Avatar
    Join Date
    Feb 2011
    Location
    *nullptr
    Posts
    2,657
    Quote Originally Posted by antred View Post
    If you were thinking of using unions as a convenient alternative to reinterpret_cast ...
    I was actually thinking just the opposite. It the union's members are of same sized types, there is no need to use unions at all there.

    As C++11 supports non POD objects inside an union, shouldn't reinterpret_cast always work, if the sizeof the union members are exactly the same ?

    eg:
    Code:
    union foo
    {
        TypeA bar;
        TypeB xip;
    };// sizeof(TypeA) == sizeof(TypeB)
    In the above case, shouldn't casting a TypeA object to TypeB solve the same problem more conveniently ?
    Last edited by manasij7479; 05-23-2012 at 12:52 PM.

  12. #12
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,656
    To quote from C99, structs within a union that share initial common members are treated as a special case.
    Quote Originally Posted by c99
    With one exception, if the value of a member of a union object is used when the most recent store to the object was to a different member, the behavior is implementation-defined.70)
    One special guarantee is made in order to simplify the use of unions: If a union contains several structures that share a common initial sequence (see below), and if the union object currently contains one of these structures, it is permitted to inspect the common initial part of any of them anywhere that a declaration of the completed type of the union is visible. Two structures share a common initial sequence if corresponding members have compatible types (and, for bit-fields, the same widths) for a sequence of one or more initial members.
    The example being
    Code:
    union {
      struct {
        int alltypes;
      }n;
      struct {
        int type;
        int intnode;
      } ni;
      struct {
        int type;
        double doublenode;
      } nf;
    }u;
    u.nf.type = 1;
    u.nf.doublenode = 3.14;
    /* ... */
    if (u.n.alltypes == 1)
      if (sin(u.nf.doublenode) == 0.0)
        /* ... */
    I would think that the C++ standard would inherit a similar clause.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. C++ executable sizes
    By MK27 in forum C++ Programming
    Replies: 19
    Last Post: 04-09-2010, 06:50 AM
  2. File sizes
    By bradszy in forum C++ Programming
    Replies: 18
    Last Post: 04-28-2008, 05:24 AM
  3. SQL Variable sizes
    By jverkoey in forum Tech Board
    Replies: 4
    Last Post: 01-23-2005, 05:59 PM
  4. Getting file sizes
    By mart_man00 in forum C Programming
    Replies: 22
    Last Post: 04-01-2003, 09:17 AM
  5. Font Sizes
    By novacain in forum Windows Programming
    Replies: 5
    Last Post: 11-06-2002, 12:23 PM