How to initialize an unnamed structure element within a named union - c

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?

Related

Access type flag of unknown void pointer based on two possible structs?

I am currently working on my own octree in C. The tree will contain a few billion objects, so memory efficiency is key. To achieve this I currently use one struct with a flag and a union, but I think it is not clean and it is wasting space for the inner node because I only need an 8-bit flag but memory is being reserved for the 64-bit index. My code currently is as follows:
typedef struct _OctreeNode
{
uint64_t location_code;
union
{
uint8_t child_exists;
uint64_t object_index;
} data;
uint8_t type;
} OctreeNode;
I would like to split this up into two different structs. One leaf node and one inner node. As follows:
typedef struct _OctreeInnerNode
{
uint64_t location_code;
uint8_t child_exists;
uint8_t type;
} OctreeInnerNode;
typedef struct _OctreeLeafNode
{
uint64_t location_code;
uint64_t object_index;
uint8_t type;
} OctreeLeafNode;
Now the problem arises with my unordered map based on the hash of the location code. It uses a void pointer, so storing two different structs is not a problem. I know a possibility would be to have the flag be the first element and dereference the pointer to the flag datatype to derive the type, like so:
typedef struct _OctreeLeafNode
{
uint8_t type;
uint64_t location_code;
uint64_t object_index;
} OctreeLeafNode;
void
func(void* node)
{
uint8_t type = *(uint8_t*)node;
if (type == LEAF_NODE) {
OctreeLeafNode* leaf_node = (OctreeLeafNode*)node;
}
}
I was wondering if there is a cleaner way. Or is this not recommended? How would I be supposed to deal with multiple possibilities for structs and void pointers?
Thanks in advance!
This a method that is used commonly in C.
But just put these field at start of structure (first field) and never change their position. In addition, you need to keep them in all your structures.
A common sample for this approach is the version field in structures (or type in your case). You can keep them at start of structure, and then check structure version by similar method. something like this:
struct _base {
uint8_t ver;
};
#define TYPE_OLD 0
struct _a_old {
struct _base info;
uint8_t a;
};
#define TYPE_NEW 1
struct _a_new {
struct _base info;
uint8_t a;
uint8_t b;
};
Now you can identify different types by casting your data to struct _base and checking ver field.
unsigned char* buf = ...
switch (((struct _base*)buf)->ver)
{
case TYPE_OLD:
{
struct _a_old* old = (struct _a_old*)buf;
// ...
break;
}
case TYPE_NEW:
{
struct _a_new* old = (struct _a_new*)buf;
// ...
break;
}
default:
// ...
}
This will work, assuming the type field is first in each struct. A pointer to a struct may safely be converted to a pointer to its first member, so assuming your structs look like this:
typedef struct _OctreeInnerNode
{
uint8_t type; // type goes first
uint8_t child_exists; // put uint8_t members together to keep size down
uint64_t location_code;
} OctreeInnerNode;
typedef struct _OctreeLeafNode
{
uint8_t type; // type goes first
uint64_t object_index;
uint64_t location_code;
} OctreeLeafNode;
You can cast either a OctreeInnerNode * or a OctreeLeafNode * to a uint8_t *. Then this is possible:
void func(void* node) {
uint8_t type = *(uint8_t*)node;
if (type == LEAF_NODE) {
OctreeLeafNode *leafNode = node;
...
} else if (type == INNER_NODE) {
OctreeInnerNode *innerNode = node;
...
}
}
...
OctreeLeafNode leaf = { LEAF_NODE, 2, 3 };
OctreeInnerNode inner = { INNER_NODE, 5, 1 };
func(&leaf);
func(&inner);
This is guaranteed as per section 6.7.2.1p15 of the C standard:
Within a structure object, the non-bit-field members and the
units in which bit-fields reside have addresses that increase in
the order in which they are declared. A pointer to a structure
object, suitably converted, points to its initial member (or
if that member is a bit-field, then to the unit in which it
resides), and vice versa. There may be unnamed padding within
a structure object, but not at its beginning

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)

Unable to access member of anonymous structure inside 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;

Resources