Multiple names for the same struct in c - 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);
...
}

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

sizeof anonymous nested struct

Suppose I have structure I'm using to model various packet formats:
#define MaxPacket 20
typedef struct {
u8 packetLength;
union {
u8 bytes[MaxPacket];
struct {
u16 field1;
u16 field2;
u16 field3;
} format1;
struct {
double value1;
double value2;
} format2;
};
} Packet;
I can expect that sizeof(Packet) will be 21. But is there any way to do something like:
sizeof(Packet.format2)
? I've tried that, but the compiler is not happy. Obviously, I could pull the format1 out as a separate typedef and then I could sizeof(format1). But I'm curious if I have to through all of that. I like the hierarchical composition of the formats. This is with gcc on an 8bit processor.
I'm equally interested if there's a way to use the nested type. IF I have to do a lot of
aPacketPointer->format2.value1; // not so onerous, but if the nesting gets deeper...
Then sometimes it would be nice to do:
Packet.format2 *formatPtr = &aPacketPointer->format2;
formatPtr->value2; // etc
Again, refactoring into a bunch of preceding typedefs would solve this problem, but then I lose the nice namespacing effect of the nested dotted references.
For something that will work even in C90, you can use a macro modeled on your toolchain's offsetof() macro:
#define sizeof_field(s,m) (sizeof((((s*)0)->m)))
Adjust it accordingly if your toolchain's offsetof() macro isn't based on casting 0 to a pointer to the structure's type.
When I use it like so:
std::cout << sizeof_field(Packet,format1) << std::endl;
std::cout << sizeof_field(Packet,format2) << std::endl;
I get the output:
6
16
For your second question, if you're willing to rely on GCC's typeof extension you can create a similar macro for declaring pointers to your nested anonymous structs:
#define typeof_field(s,m) typeof(((s*)0)->m)
...
typeof_field(Packet,format2)* f2 = &foo.format2;
To be honest, I find that construct pretty ugly, but it might still be better than other options you have available.
GCC documents that the "operand of typeof is evaluated for its side effects if and only if it is an expression of variably modified type or the name of such a type", so the apparent null pointer deference should not result in undefined behavior when a variable length array is not involved.
Using C11 or C99, create a dummy compound literal and seek its size.
printf("%zu\n", sizeof( ((Packet){ 0, { "" }}).format2 ));
Output
16
You can just give those nested structs a name, no need for a typedef. Like this:
typedef struct {
u8 packetLength;
union {
u8 bytes[MaxPacket];
struct myformat1 {
u16 field1;
u16 field2;
u16 field3;
} format1;
struct myformat2 {
double value1;
double value2;
} format2;
};
} Packet;
Then you can write e.g. sizeof(struct myformat1), declare variables of that type, etc.
You could also add a typedef afterwards, e.g.
typedef struct myformat1 myformat1;

How do I safely put two variable sized datatypes (structs) in a single struct?

I'm trying to construct some C structs that themselves need to hold multiple structs. It looks something like this:
typedef struct hdr_t {
uint16_t a;
uint16_t b;
uint8_t c;
uint8_t d[3];
uint64_t e;
uint8_t f[];
} hdr_t;
typedef struct {
uint64_t data;
} pyld_t;
typedef struct {
hdr_t hdr;
pyld_t pyld;
} msg_t;
When I compile this, depending on the compiler and settings, I get warnings.
./file.h:55:24: warning: field 'hdr' with variable sized type 'hdr_t'
(aka 'struct hdr_t') not at the end of a struct or class is a GNU extension
[-Wgnu-variable-sized-type-not-at-end]
hdr_t hdr;
For this example, I'm using clang 6.1.0:
$ clang --version
Apple LLVM version 6.1.0 (clang-602.0.53) (based on LLVM 3.6.0svn)
Target: x86_64-apple-darwin14.5.0
Thread model: posix
The warning complain that what I'm doing is a non-portable GNU extension, which I'd rather avoid. What can I do to solve this? Is there not a safe way to put multiple structs in a struct? Surely that's not the case.
A C structure can be variable-size only in the sense that it may contain a "flexible array member" as its last member. C forbids such a structure type from being the type of any structure member or array element, though GCC permits that as an extension.
Even if GCC (or clang) accepted your declaration, I doubt it would mean what you think it means. Every member of a structure has a fixed offset relative to the beginning of the structure, determined statically at compile time. As a result, your msg_t cannot provide sufficient space for arbitrary hdr.f, and quite possibly it provides no space at all, especially if you enable structure packing. Thus, accessing hdr.f of a msg_t could easily access the message data, which I suppose is not what you expect.
I guess the whole point is to map a structure to a byte buffer, but if the underlying data format has variable-length elements in the middle then you just can't directly map a single C structure to it. You could, however, create and use an index structure:
typedef struct {
hdr_t *hdr;
pyld_t *pyld;
} msg_index_t;
That would make it easier to handle mapping a pair of structures to your buffer.
You could use an union:
typedef struct {
..stuff
}type_f1;
typedef struct {
..stuff
}type_f2;
typedef struct {
..stuff
}type_f3;
typedef union {
type_f1 f1;
type_f2 f2;
type_f3 f3;
uint8_t rawdata[MAX_RAWDATA];
}type_f;
typedef struct hdr_t {
uint16_t a;
uint16_t b;
uint8_t c;
uint8_t d[3];
uint64_t e;
type_f f;
} hdr_t;
typedef struct {
uint64_t data;
} pyld_t;
typedef struct {
hdr_t hdr;
pyld_t pyld;
} msg_t;
There's lots of solutions that will fix the issue. For my specific problem, just changing the declaration of hdr_t from this:
typedef struct hdr_t {
uint16_t a;
uint16_t b;
uint8_t c;
uint8_t d[3];
uint64_t e;
uint8_t f[];
} hdr_t;
to this:
typedef struct hdr_t {
uint16_t a;
uint16_t b;
uint8_t c;
uint8_t d[3];
uint64_t e;
uint8_t *f; //Use pointer instead of variable sized array
} hdr_t;
I'm not sure why the original code was using the array, but it wasn't necessary.

When are anonymous structs and unions useful in C11?

C11 adds, among other things, 'Anonymous Structs and Unions'.
I poked around but could not find a clear explanation of when anonymous structs and unions would be useful. I ask because I don't completely understand what they are. I get that they are structs or unions without the name afterwards, but I have always (had to?) treat that as an error so I can only conceive a use for named structs.
Anonymous union inside structures are very useful in practice. Consider that you want to implement a discriminated sum type (or tagged union), an aggregate with a boolean and either a float or a char* (i.e. a string), depending upon the boolean flag. With C11 you should be able to code
typedef struct {
bool is_float;
union {
float f;
char* s;
};
} mychoice_t;
double as_float(mychoice_t* ch)
{
if (ch->is_float) return ch->f;
else return atof(ch->s);
}
With C99, you'll have to name the union, and code ch->u.f and ch->u.s which is less readable and more verbose.
Another way to implement some tagged union type is to use casts. The Ocaml runtime gives a lot of examples.
The SBCL implementation of Common Lisp does use some union to implement tagged union types. And GNU make also uses them.
A typical and real world use of anonymous structs and unions are to provide an alternative view to data. For example when implementing a 3D point type:
typedef struct {
union{
struct{
double x;
double y;
double z;
};
double raw[3];
};
}vec3d_t;
vec3d_t v;
v.x = 4.0;
v.raw[1] = 3.0; // Equivalent to v.y = 3.0
v.z = 2.0;
This is useful if you interface to code that expects a 3D vector as a pointer to three doubles. Instead of doing f(&v.x) which is ugly, you can do f(v.raw) which makes your intent clear.
struct bla {
struct { int a; int b; };
int c;
};
the type struct bla has a member of a C11 anonymous structure type.
struct { int a; int b; } has no tag and the object has no name: it is an anonymous structure type.
You can access the members of the anonymous structure this way:
struct bla myobject;
myobject.a = 1; // a is a member of the anonymous structure inside struct bla
myobject.b = 2; // same for b
myobject.c = 3; // c is a member of the structure struct bla
Another useful implementation is when you are dealing with rgba colors, since you might want access each color on its own or as a single int.
typedef struct {
union{
struct {uint8_t a, b, g, r;};
uint32_t val;
};
}Color;
Now you can access the individual rgba values or the entire value, with its highest byte being r. i.e:
int main(void)
{
Color x;
x.r = 0x11;
x.g = 0xAA;
x.b = 0xCC;
x.a = 0xFF;
printf("%X\n", x.val);
return 0;
}
Prints 11AACCFF
I'm not sure why C11 allows anonymous structures inside structures. But Linux uses it with a certain language extension:
/**
* struct blk_mq_ctx - State for a software queue facing the submitting CPUs
*/
struct blk_mq_ctx {
struct {
spinlock_t lock;
struct list_head rq_lists[HCTX_MAX_TYPES];
} ____cacheline_aligned_in_smp;
/* ... other fields without explicit alignment annotations ... */
} ____cacheline_aligned_in_smp;
I'm not sure if that example strictly necessary, except to make the intent clear.
EDIT: I found another similar pattern which is more clear-cut. The anonymous struct feature is used with this attribute:
#if defined(RANDSTRUCT_PLUGIN) && !defined(__CHECKER__)
#define __randomize_layout __attribute__((randomize_layout))
#define __no_randomize_layout __attribute__((no_randomize_layout))
/* This anon struct can add padding, so only enable it under randstruct. */
#define randomized_struct_fields_start struct {
#define randomized_struct_fields_end } __randomize_layout;
#endif
I.e. a language extension / compiler plugin to randomize field order (ASLR-style exploit "hardening"):
struct kiocb {
struct file *ki_filp;
/* The 'ki_filp' pointer is shared in a union for aio */
randomized_struct_fields_start
loff_t ki_pos;
void (*ki_complete)(struct kiocb *iocb, long ret, long ret2);
void *private;
int ki_flags;
u16 ki_hint;
u16 ki_ioprio; /* See linux/ioprio.h */
unsigned int ki_cookie; /* for ->iopoll */
randomized_struct_fields_end
};
Well, if you declare variables from that struct only once in your code, why does it need a name?
struct {
int a;
struct {
int b;
int c;
} d;
} e,f;
And you can now write things like e.a,f.d.b,etc.
(I added the inner struct, because I think that this is one of the most usages of anonymous structs)

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