Unable to access member of anonymous structure inside union - union

I am using a union and an anonymous structure inside it. I want to know how I can access the structure member inside it. Like if i want to access G variable of structure using union variable then how can i do that. Please help :)
typedef union
{
uint8_t All;
struct
{
uint8_t G:1;
uint8_t O_B:1;
uint8_t Unused:1;
uint8_t W1:1;
uint8_t W2:1;
uint8_t Y1:1;
uint8_t Y2:1;
uint8_t IAQ:1;
};
} _UNION_VARIABLE;
I am getting compilation error for accessing structure member like below :
_UNION_VARIABLE sg_RefreshVar;
sg_RefreshVar.G = false;
Error :
#137 union "<unnamed>" has no field "G"

You need to give it a name
typedef union
{
uint8_t All;
struct
{
uint8_t G:1;
uint8_t O_B:1;
uint8_t Unused:1;
uint8_t W1:1;
uint8_t W2:1;
uint8_t Y1:1;
uint8_t Y2:1;
uint8_t IAQ:1;
} bit_field;
} _UNION_VARIABLE;
and then you can go
_UNION_VARIABLE.bit_field.G;

Related

Multiple names for the same struct in c

Is it possible to create multiple names for the same struct in C?
The idea is that data structures in a communication protocol which has the same layout but different names, could share the same definition.
Example:
struct flags_type1 {
uint8_t flag1;
uint8_t flag2;
};
struct flags_type2 {
uint8_t flag1;
uint8_t flag2;
};
/* The flag layout for type 2 is identical to type 1, so somehow
* just reuse the struct for type 1, but with a new name.
* (For readability in the implementation. */
/* *** HERE: Insert solution code here. Something with typedef? *** */
struct flags_type3 {
uint8_t flag1;
uint8_t flag2;
uint8_t flag3;
};
struct msg_object {
uint8_t type_id_code;
union {
struct flags_type1 type1;
struct flags_type2 type2;
struct flags_type3 type3;
} flags;
uint8_t payload[7];
};
/* Utilization: */
struct msg_object *msg;
switch (msg->type_id_code) {
case TYPE1:
do_things_type1(msg->flags.type1);
break;
case TYPE2:
do_things_type2(msg->flags.type2);
break;
case TYPE3:
do_things_type3(msg->flags.type3);
break;
}
Motivation:
I am implementing a communication protocol which can transmit message objects which has different types (Specifically, SDOs in CANopen). Each object has a 5-bit field of status flags, and some of the objects has an identical layout of this field. There is also a 3-bit field which identifies the object type. These two fields, are fitted into a single byte.
The idea is thus to utilize the correct flag layout based on the type identifier. To make this choice of flag layout intuitive, it seems sensible to make all the type names present, without defining the same layout twice.
I suppose this, technically, is a inheritance question.
//audun
You can't have two tagged types (tagged types are structs, unions, or enums) with different tags (what comes after the struct/union/enum keyword)
point to the same type (you can think of struct x like a compile-time pointer pointing to the type definition). In other words, struct x can never alias struct y. But you can have different typedefs pointing to the same type.
typedef struct flags_type1 {
uint8_t flag1;
uint8_t flag2;
} flags_type1; //flags_type1 is now both a tag and a global typename
typedef flags_type1 flags_type2; //flags_type2 == flags_type1
You might want flags_type1 and flags_type2 to have different types, though (for the sake of the functions), in which case in pure C you can do:
struct flags2 { struct flags1 embedded; }
With this you'll then have to mention the member name (embedded) to access the members. This is unavoidable in straight C (if you don't want to use a macro for the member set), though on gcc/clang with -fms-extensions you can do:
struct flags2 { struct flags1; }
//w/ -fms-extensions, reuseses the body and
//makes struct flags2 implicitly convertible to struct flags1
and then access the members directly.
Apart from this, there's always macros.
I'm not sure exactly what your trying to achieve. If I'm not misunderstanding this, I guess it can be done with typedef. Like:
struct flags_type {
uint8_t flag1;
uint8_t flag2;
};
typedef struct flags_type type1;
typedef struct flags_type type2;
You don't need typedefs, and you can nest structure definitions:
struct msg_object {
uint8_t type_id_code;
union {
struct t01 {
uint8_t flag1;
} type1;
struct t02 {
uint8_t flag1;
uint8_t flag2;
} type2;
struct t03 {
uint8_t flag1;
uint8_t flag2;
uint8_t flag3;
} type3;
} flags;
uint8_t payload[7];
};
The code for the handler:
switch (msg->type_id_code) { // may need to mask here ...
case TYPE1:
do_things_type1(msg->flags.type1); // <<-- passed BY VALUE
break;
...
The called function could be:
void do_things_type1(struct t1 this) {
printf("%x", this.flag1 & 0xff);
...
}

array take size of struct in union

I have a union in a project i'm working on that represents a USB joystick report:
union {
struct{
uint8_t xaxis;
uint8_t yaxis;
uint8_t xraxis;
uint8_t yraxis;
uint8_t zraxis;
uint8_t slider;
uint8_t buttons8;
uint8_t buttons16;
};
uchar buffer[8];
} report;
this way i can easily put the values into the struct members and use the buffer member to send that data over USB, however I end up modifying this union for different projects (different resolutions on the axis, more/less buttons etc) so then i have to work out what the new size of the struct is to declare the array with the same size.
is there a way to automatically make the array the same size? i thought of using sizeof which requires me to change the struct like this:
union {
struct _data{ // either this
uint8_t xaxis;
uint8_t yaxis;
uint8_t xraxis;
uint8_t yraxis;
uint8_t zraxis;
uint8_t slider;
uint8_t buttons8;
uint8_t buttons16;
} data; // or this
uchar buffer[8];
} report;
but then i can no longer put data into the struct like this:
report.xaxis = value;
but instead:
report.data.xaxis = value;
which i don't want.
is there a way to do this cleanly?
Step 1 is to get a standard C compiler. Then you can use an anonymous struct. To get the appropriate size for the array, use a struct tag, which is only needed internally by the union.
typedef union {
struct data {
uint8_t xaxis;
uint8_t yaxis;
uint8_t xraxis;
uint8_t yraxis;
uint8_t zraxis;
uint8_t slider;
uint8_t buttons8;
uint8_t buttons16;
};
uint8_t buffer[sizeof(struct data)];
} report_t;
...
report_t r;
r.xaxis = 123;
You could use offsetof() for this with the last element in the struct
union
{
struct data
{
uint8_t xaxis;
uint8_t yaxis;
uint8_t xraxis;
uint8_t yraxis;
uint8_t zraxis;
uint8_t slider;
uint8_t buttons8;
uint8_t buttons16;
};
uint8_t buffer[offsetof(struct data, buttons16)+1];
} report;
The solutions other people have proposed here will work. However, they are all hacks, due to your use of a union for ease of conversion to bytes. There is a cleaner solution, which is to do away with the union. Simply make your struct the top-level type, and have your function that sends data over USB take parameters of (void * data, size_t length) . Then, you can easily send any data type over USB.

Using pointers within structure for assigning string

I am trying to assign a string to a pointer which is in the structure. Even though, I am able to initialise the string to pointer successfully, when I try to use the string(access the pointer), I get some random values. How should I solve the problem. Following is my code:
typedef struct
{
uint8_t LOG_ID;
uint8_t timestamp;
uint8_t loglength;
uint8_t checksum;
uint8_t *payload;
} Log;
Log LB_t;
void main(){
LB_t.LOG_ID=1;
LB_t.timestamp=3;
LB_t.loglength=17;
LB_t.checksum=89;
LB_t.payload="LED initialised";
log_item(&LB_t,17);
}
void log_item(uint8_t *logptr,uint8_t length){
while(length!=0){
CB_buffer_add_item(tx,*logptr);
length=length-1;
logptr++;
}
}
Is there any alternate way in which I can access the pointer?
OK, I get it , you expect 'payload' to be inside the struct. Its not, just the pointer. You need to do this
typedef struct
{
uint8_t LOG_ID;
uint8_t timestamp;
uint8_t loglength;
uint8_t checksum;
uint8_t payload[100];
} Log;
and then
strncpy(LB_t.payload, "LED initialised", 100);
you probaly want to make the 100 a const or #define somehwere. And change yr 17 to sizeof(Log)

How to initialize an unnamed structure element within a named union

I am using a union and an anonymous structure inside it. I want to know how I can initialize the structure members inside it. how can i do that? Please help :)
typedef union
{
uint8_t All;
struct
{
uint8_t G:1;
uint8_t O_B:1;
uint8_t Unused:1;
uint8_t W1:1;
uint8_t W2:1;
uint8_t Y1:1;
uint8_t Y2:1;
uint8_t IAQ:1;
};
} _UNION_VARIABLE;
_UNION_VARIABLE bit_field_array[5] = { {.G=1, .O_B=0, ...}, {.G=0, .O_B=1, ...},.....};
Is this correct?

polymorphism in c and buffers

I have this union:
typedef union Message
{
message_base base;
message_with_parameters parameters;
reply_message reply;
buffer_t *buffer; // can't figure out what to put here
} message;
message_with_parameters has a message_base as the first field and reply_message has a message_with_parameters as as the first field which in turns has message_base as as the first field.
So basically I can access any of them and I'll still get all the data I need, however I am getting a buffer from my driver and now I want to serialize it into the message.
I already know that the pointer to the buffer is wrong as it won't correlate with my structs but I can't have a fixed size buffer.
Somewhere along the way I want to do this:
m->buffer = buff->payload;
And no matter what kind of data type I have, it will still serialize.
How can it be done?
EDIT:
Here are my structs:
typedef struct MessageBase
{
uint32_t u32DeviceID;
uint32_t u32CoreID;
uint16_t u16Class;
uint16_t u16CRC;
uint8_t u8OpCode;
void (*states [MAX_OPCODES]) (void *);
} message_base;
typedef struct MessageWithParameters
{
message_base base_class;
uint8_t u8Param1;
uint8_t u8Param2;
} message_with_parameters;
typedef message_with_parameters reply_message;
typedef union Message
{
message_base base;
message_with_parameters parameters;
reply_message reply;
} message;
its because the data in the buffer isn't part of the union.
buffer_t* buffer is a pointer, so the pointer is part of the union, not the data which it points at
you probablly want to do something like
m = (message*) buff->payload;

Resources