Jim Fell
Jim Fell

Reputation: 14256

What is the reason for naming unions?

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?

Upvotes: 1

Views: 122

Answers (4)

Rob K
Rob K

Reputation: 8926

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.

Upvotes: -1

scasady
scasady

Reputation: 21

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

Upvotes: 2

AlexBriskin
AlexBriskin

Reputation: 62

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++.

Upvotes: 1

Zbynek Vyskovsky - kvr000
Zbynek Vyskovsky - kvr000

Reputation: 18825

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.

Upvotes: -1

Related Questions