1

Why name a union if the compiler always treats the object as anonymous, regardless as to whether or not the union is named?

My implementation looks like this:

typedef struct _DMessageHeader {
    union _msgId {
        unsigned char ucMsgId;
        unsigned short usMsgId;
        unsigned long ulMsgId;
        unsigned long long ullMsgId;
    } msgId;
} DMSG_HDR, *PDMSG_HDR;

I'd like to be able to access it like this, but the compiler throws an error:

PDMSG_DESC ptMsg->hdr.msgId = id_in;

It only allows me to directly access the union member like this:

PDMSG_DESC ptMsg->hdr.msgId.ucMsgId = id_in;

Any thoughts as to why this is, or how I may access the union by name?

timrau
  • 22,578
  • 4
  • 51
  • 64
Jim Fell
  • 13,750
  • 36
  • 127
  • 202
  • What is the type of `id_in`? Why do you expect to be able to assign a thing of one type to a thing of a different type? – Rob K Jan 27 '16 at 22:56
  • 1
    Those typedefs were never needed in C++, not even in C++98 and still not in C++14. `_D` is plain wrong. – MSalters Jan 29 '16 at 21:40

4 Answers4

2

Its a type thing. The compiler can't convert an int something to a union. You can however overload the "=" operator to do it.

scasady
  • 21
  • 2
1

I'm not sure why would you use union in this case at all. Please note that the size of the struct is 8 bytes (size of long long) on my 64bit machine.

#include <iostream>
using std::cout;
using std::endl;
typedef struct _DMessageHeader {
    union _msgId {
        unsigned char ucMsgId;
        unsigned short usMsgId;
        unsigned long ulMsgId;
        unsigned long long ullMsgId;
    }  msgId;
} DMSG_HDR, *PDMSG_HDR;

int main( int argc , char ** argv, char ** env)
{
    cout<<"sizof DMessageHeader"<<sizeof(DMSG_HDR)<<endl;
    return 0;
}

If all you store in union msgid is a single id of varying length (1 - 8) bytes depending on your architecture) and you have no memory constrains rewrite your struct as following:

typedef struct _DMessageHeader {
unsigned long long msgId;
} DMSG_HDR, *PDMSG_HDR;
DMSG_HDR hdr;
hdr.msgId = id_in;

Also I suggest reading this thread for thorough discussion about using unions in C++.

Community
  • 1
  • 1
  • Although this addresses a problem in the post, it does not answer the question, and should not be marked as the accepted answer. – pigi5 Jan 16 '20 at 22:25
-1

There can be various reasons:

  • There are restrictions in original C compiler which doesn't allow anonymous unions. In other words the structure may be used by both C and C++ programs.
  • You may want to work with whole union (moving, assigning etc.) and this allows you to define the variable of such types.
Zbynek Vyskovsky - kvr000
  • 18,186
  • 3
  • 35
  • 43
-1

Because you're not using an anonymous union in your example. You've given your union member of your struct a name, msgId, and it has members. You can't assign directly to the union itself, you have to assign to a member of the union.

An anonymous union would be as follows:

union {
    int i;
    char c;
};
i = 1;

or

struct s 
{
    int i1;
    union {
        int i2;
        char c2;
    };
};

s s1.i2 = 5;

The union in struct s has no name, and it's members are accessed directly.

ETA:

Assuming your variable id_in is an unsigned char since you assign it to the unsigned char member in the example that works, why would you expect this to work?

PDMSG_DESC ptMsg->hdr.msgId = id_in;

ptMsg->hdr.msgId is not of type unsigned char nor is it an implicitly convertible type. ptMsg->hdr.msgId is of type _DMessageHeader::_msgId.

"A union is a special class type that can hold only one of its non-static data members at a time." (http://en.cppreference.com/w/cpp/language/union) It's a class type and you've defined no conversion operators or constructors. Of course it won't allow the assignment.

Rob K
  • 8,757
  • 2
  • 32
  • 36
  • I don't want an anonymous union. I want to be able to reference the union by name, not it's members, since its members all occupy the same memory space anyways. Coding is more complex if I have to reference each member by name, rather than a common shared reference to the union name. – Jim Fell Jan 27 '16 at 19:09
  • Then why are you talking about anonymous unions? Nothing about your example shows the compiler treating your union as anonymous. It shows the compiler refusing to assign a thing of one type to a thing of another type. – Rob K Jan 27 '16 at 22:59