Audun Knudsroed
Audun Knudsroed

Reputation: 23

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

Upvotes: 1

Views: 4098

Answers (3)

joop
joop

Reputation: 4503

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);
        ...
}

Upvotes: 0

Petr Skocik
Petr Skocik

Reputation: 60058

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.

Upvotes: 3

4386427
4386427

Reputation: 44274

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;

Upvotes: 2

Related Questions