Приведите переменную к типу объединения, определенному в определении структуры - PullRequest
0 голосов
/ 19 марта 2019

На самом деле у меня есть некоторые трудности в C, чтобы привести беззнаковую переменную int к типу объединения, который объявлен в объявлении типа структуры.

Мне нужно установить переменную таким же образом, как при записи поля объединения, определенного в структуре.

Декларация во включенном заголовочном файле:

typedef struct {
    [...]

    union {
        unsigned long COMPLETE_VALUE;
        struct {
            unsigned long   UPPER:16;           /* [15:0] */
            unsigned long   LOWER:16;           /* [31:16] */
        } SUB_STRUCT;
    } UNION;

    [...]
} STRUCT_TYPE;

Переменная в исходном файле c:

STRUCT_TYPE *pStructure;                        /* the reference structure */
unsigned long dummyVar;                         /* dummy variable */

/* writing the upper field in the structure */
pStructure->UNION.SUB_STRUCT.UPPER = some_value;

Вопрос: Можно изменить значение "dummyVar", используя внутренние типы объединения типа структуры STRUCT_TYPE? Можно ли привести переменную к объединению, определенному внутри структуры и имеющему доступ к полю подструктуры?

Было бы очень полезно, если бы переменную можно было изменить, как показано ниже, или аналогичным образом:

((<CAST>) dummyVar).UNION.SUB_STRUCT.UPPER = some_value;

Примечания: - Объявление STRUCT_TYPE не может быть изменено. - Структура pStructure не может быть написана или отредактирована. - Поведение доступа pStructure должно быть воспроизведено в dummyVar.

Возможно ли это в любом случае в C?

Заранее спасибо!

Martin

Ответы [ 2 ]

1 голос
/ 19 марта 2019

Можно изменить значение "dummyVar", используя внутренние типы объединения типа структуры STRUCT_TYPE?

Несмотря на все размеры и представления, нет, этов вашем примере невозможно привести что-либо к внутреннему типу объединения, потому что типы типов применимы только к скалярным типам.Существуют игры, в которые можно играть с указателями и хрупким дублированием кода, но я настоятельно рекомендую не использовать такие махинации, и я отказываюсь приводить пример.

Однако, если вы хотите установить значение dummyVar равнымзначение, соответствующее STRUCT_TYPE.UNION.COMPLETE_VALUE для некоторых конкретных значений UPPER и LOWER, затем в C99 и позже вы можете сделать это через составной литерал:

dummyVar = ((STRUCT_TYPE) { .UNION = { .SUB_STRUCT = { some_upper, some_lower } } }).UNION.COMPLETE_VALUE;

Обратите внимание, что хотя (STRUCT_TYPE)Часть напоминает приведение, это скорее всего часть синтаксиса составного литерала.Вы не можете приводить к типу структуры больше, чем к типу объединения.

В качестве альтернативы, в единицах перевода, где STRUCT_TYPE не определено, вы можете написать составной литерал для внутреннего типа объединения, нобыло бы намного хуже.Поскольку у этого типа нет тега или псевдонима, составной литерал этого типа должен будет воспроизвести его полное определение.Тип такого составного литерала технически не совместим с типом члена структуры в любой единице перевода, где оба определены, но с практической точки зрения я не вижу причин сомневаться в том, что вы получите то же значение для dummyVar в любом случае.

1 голос
/ 19 марта 2019

Можно изменить значение "dummyVar", используя внутренние типы объединения типа структуры STRUCT_TYPE?

Вероятно, нет, поскольку у вас есть это:

typedef struct {
    [...]

    union {

Я полагаю, [...] означает, что там размещены члены структуры.

Возможно ли преобразовать переменную в объединение, определенное в структуре, и получить доступ к полю субэлемента?структура?

Нет, если только это не начальная часть структуры, и даже тогда она сомнительна.Возможно, было бы разумнее разорвать объединение как отдельный typedef, который не тесно связан со структурой.

Кроме того, битовые поля, используемые объединением, не стандартизированы, и вы можете 'не может знать, как они попадают в память, переносимо.

Самое умное, что нужно сделать здесь, это, вероятно, забыть все о структуре и просто сделать

uint32_t u32 = ...
uint16_t ms = u32 >> 16;
uint16_t ls = u32 & 0xFFFFu;

Этот код переносим независимо от битреализации полей и endianess.

...