7

I want to create a union in which the biggest member is a 32 bit integer. This is what will be mainly written to. Then there are four 8 bit variables, probably char types that will each refer to a different section of the 32 bit integer kind of like:

   union {
   int32 myint;
   char char1 [7:0];
   char char2 [15:8];
   char char3 [23:16];
   char char4 [31:24];
   }

But I am not sure how to do this in C++.

timrau
  • 22,578
  • 4
  • 51
  • 64
quantum231
  • 2,420
  • 3
  • 31
  • 53
  • 3
    Is this for C++ or C? – Tas Jan 11 '16 at 23:07
  • 1
    Why `char`? Bitfields already are based on `int`. – πάντα ῥεῖ Jan 11 '16 at 23:07
  • what I wrote is not correct C++. Could you elabore what you mean by bit field? Are you trying to say that if I use int for char1 to char4 then the above union is syntactically correct? – quantum231 Jan 11 '16 at 23:13
  • If I recall correctly, it is illegal to in c++ to assign to one member of an union and read from another. What exactly are you trying to achieve and are you writing c or c++ code? The rules for unions are different between the two languages – MikeMB Jan 11 '16 at 23:35
  • MikeMB, my question was related to C++. In my understanding the rules should be the same between the two languages but since I am not an expert I accept what you are saying. Anyway, from the answers given below I have found my solution. Thanks. – quantum231 Jan 11 '16 at 23:38
  • @quantum231: From [cppreference.com](http://en.cppreference.com/w/cpp/language/union): `...it's undefined behavior to read from the member of the union that wasn't most recently written. Many compilers implement, as a non-standard language extension, the ability to read inactive members of a union.` In particular Visual studio doesn't make any claims, that reading from a member that was not the last one you assigned to is legal (I'm not sure, what the situation is in gcc or clang). The rules regarding unions are definitively not the same for (standard) c and c++. – MikeMB Jan 11 '16 at 23:45
  • My program is working and giving expected result – quantum231 Jan 12 '16 at 00:20
  • 1) Use standard types instead of homebrew-names for fixed-width types. C provides `intN_t` in `stdint.h` for this reason. 2) In general it is better to use an unsigned for such applications. 3) If that is to (de)serialise the `int32`, you better use shift/mask operations. A good compiler might detect these patterns and use byte-accesses on you platform. That way you omit the extra store and don't have to care about implementation details. – too honest for this site Jan 12 '16 at 08:10

4 Answers4

8

This may work:

union {
   int32 myint;
   char chars[4];
};
John Hascall
  • 9,176
  • 6
  • 48
  • 72
Cecilio Pardo
  • 1,717
  • 10
  • 13
6

I didn't understand if you wanted one 32bits interger AND 4 8bits variables or one 32bits interger split in 4 8bits variables, but anyway you should try something like this :

union yourUnion {
    int32 yourInt;
    struct {
        int32 var1 : 8;
        int32 var2 : 8;
        int32 var3 : 8;
        int32 var4 : 8;
    } yourSplitInterger;
};

Hope it helps.

Maxattak
  • 96
  • 1
  • 3
  • yes, I was going to split it up. This will be sufficient. – quantum231 Jan 11 '16 at 23:20
  • There is no guarantee the bitfields will be stored in a single `int32`. Also each field is signed. – too honest for this site Jan 12 '16 at 08:12
  • According to [cppreference](http://en.cppreference.com/w/c/language/bit_field), bit fileds are usually packed together, so no, indeed, there is no guarantee they will be stored in a single `int32` but I think it's the best practice for what OP wants to do. Also, I'm not sure the fact that the fields are signed really matters considering that OP will problably write `char` into those bit fileds. – Maxattak Jan 12 '16 at 15:45
  • 1) please use `@name` to address a comment. Otherwise it likely goes unnoticed (like yours did) 2) "usually" is quite a weak foundation. 3) `cppreference` is not authoritative. There is a standard for both, C and C++. Much better basis. 3) No, it is not. Because the single fields will be signed now, which is very likely not what he wants. 4) Why not just use an array of `uint8_t`. That is guaranteed to have no padding. 5) All such approaches are still implementation dependent, as they do not respect endianess. – too honest for this site Jan 12 '16 at 18:35
5

You can use this:

union myUnion {
    int32   myint;
    struct {
        char char1;
        char char2;
        char char3;
        char char4;
    } myChars;
};

or with uint8_t:

union myUnion {
    uint32_t  myint;
    struct {
        uint8_t b1;
        uint8_t b2;
        uint8_t b3;
        uint8_t b4; // or number them in reverse order
    } myBytes;
};

See here.

Danny_ds
  • 11,201
  • 1
  • 24
  • 46
2
union intBytes {
    int32   myInt;
    struct {
        char char1;
        char char2;
        char char3;
        char char4;
    };
    char charArray[4];
};

intBytes dummy;

Above you see that the struct wrapping char1-char4 is not assigned a name. This is called an anonymous struct. The members of an annonymous struct are directly accessible inside the scope sourrounding the struct.

Without the struct char1 - char4 would overlap inside the union and all would refer to the first byte of myInt. The annonymous struct ensures that char1 - char get layed out sequentially.

C has anonymous structs and unions. C++ (pre C++11) does NOT allow anonymous structs, only anonymous unions are defined. However, most C++ compilers (llvm, gcc) allow anonymous struct/unions.

Anonymous structs were added to C++ in C++11.

This allows you to access dummy.char4 while usually you would have to type dummy.nameOfCharStruct.char4. Since this is not standard conformant c++ (I believe it was changed in a post C++03 Standatd), you might be better of adding the name of the struct or using the array approach.

ted
  • 4,791
  • 5
  • 38
  • 84
  • 1
    Anonymous `struct`s and `union`s are part of the C standard. Not sure if C++ allows them, too. – too honest for this site Jan 12 '16 at 08:14
  • 1
    @Olaf: I guess 'C and most C++ Compilers' is to subtle, but some research shows that C++ does not allow anonymous structs while anonymous unions are ok. Here is a reference (I do not agree with all points though) http://stackoverflow.com/a/12785369/258418 – ted Jan 12 '16 at 14:59
  • I do not care about C++. For C, I provided a clear reference. But I would be careful with "most C compilers". There are still many C90-only or otherwise non-standard compilers, like MSVC. But any standard compliant C compiler **has to** support them. The standard lists both, anonymous `struct`s and `union`s as a new featrure, so likely C99 did not support any (the linked answer seems to be wrong here; also note its date). gcc did support them for longer time as an extension, though. – too honest for this site Jan 12 '16 at 15:03
  • @Olaf: I hope the clarified answer removes any confusion – ted Jan 12 '16 at 17:55