Несколько имен для одной и той же структуры в c - PullRequest
0 голосов
/ 31 мая 2018

Можно ли создать несколько имен для одной и той же структуры в C?Идея состоит в том, что структуры данных в протоколе связи, которые имеют одинаковую структуру, но разные имена, могут иметь одно и то же определение.

Пример:

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

Мотивация: Я реализую протокол связикоторый может передавать объекты сообщений, которые имеют разные типы (в частности, SDO в CANopen).Каждый объект имеет 5-битное поле флагов состояния, а некоторые объекты имеют идентичное расположение этого поля.Также есть 3-битное поле, которое идентифицирует тип объекта.Эти два поля помещаются в один байт.

Таким образом, идея состоит в том, чтобы использовать правильную разметку флага на основе идентификатора типа.Чтобы сделать этот выбор расположения флага интуитивно понятным, представляется целесообразным сделать все присутствующие имена типов без определения одного и того же расположения дважды.

Полагаю, технически это вопрос наследования.

// Аудуну

Ответы [ 3 ]

0 голосов
/ 31 мая 2018

У вас не может быть двух типов тегов (типы тегов - это структуры, объединения или перечисления) с разными тегами (которые следуют после ключевого слова struct / union / enum) указывают на один и тот же тип (вы можете думать о struct xкак указатель времени компиляции, указывающий на определение типа).Другими словами, struct x никогда не может иметь псевдоним struct y.Но вы можете иметь разные typedefs, указывающие на один и тот же тип.

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

Возможно, вы захотите, чтобы flags_type1 и flags_type2 имели разные типы (ради функций), в которыхcase в чистом C вы можете сделать:

struct flags2 { struct flags1 embedded; }

После этого вам нужно будет указать имя участника (встроено), чтобы получить доступ к членам.Это неизбежно в прямой C (если вы не хотите использовать макрос для набора элементов), хотя в gcc / clang с -fms-extensions вы можете сделать:

struct flags2 { struct flags1; }
//w/ -fms-extensions, reuseses the body and
//makes struct flags2 implicitly convertible to struct flags1

и затем получить доступ к членамнапрямую.

Кроме этого, всегда есть макросы.

0 голосов
/ 31 мая 2018

Вам не нужны typedefs, и вы можете вкладывать определения структур:


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];
        };

Код для обработчика:


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);
        ...
}
0 голосов
/ 31 мая 2018

Я не уверен, чего именно ты хочешь достичь.Если я не ошибаюсь, думаю, это можно сделать с помощью typedef.Нравится:

struct flags_type {
        uint8_t flag1;
        uint8_t flag2;
};

typedef struct flags_type type1;
typedef struct flags_type type2;
...