Перейти к содержанию
    

Инициализация объединений в С++

В Си можно сделать так:

#include <stdint.h>

// Объявляю тип объединения
typedef union {
  uint32_t  Word;
  uint16_t  HWord[2];
  uint8_t   Byte[4];
} WordUnion_t;

// Объявляю и инициализирую константный массив из 3-х объединений
const WordUnion_t MyVal[3] = {
    {.Byte = {0x12,0x34,0x12,0x34}},    // Это объединение инициализировано, как массив байт
    {.HWord = {0x5678,0x1234}},         // Это объединение инициализировано, как массив полуслов
    {.Word = 0x12345678}                // Это объединение инициализировано, как массив слов
};

С++ такое не поддерживает. Ему нельзя явно задать поле объединения, которое я хочу инициализировать.

Убираем имена полей и пытаемся инициализировать, как обычные структуры в С++:

const WordUnion_t MyVal[3] = {
  {0x12,0x34,0x12,0x34},
  {0x5678,0x1234},
  {0x12345678}
};

Компилятор и на это ругается. Только элемент MyVal[2], по его мнению, инициализирован верно.

Эксперимент показал, что инициализировать объединение в С++ можно только по полю, объявленному первым при описании этого объединения. В моем случае, по .Word. Что бы мы ни писали в инициализаторах, он расценивает это, как значение поля Word.

Собственно, вопрос: а если мне надо/удобно инициализировать моё объединение по другому полю, неужели синтаксис языка этого не позволяет?

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Да, это почти единственная сишная фишка, которой мне не хватает в плюсах.

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

union MySuperPuperUnion
{
  uint32_t  Word;
  uint16_t  HWord[2];
  uint8_t   Byte[4];
  MySuperPuperUnion(uint32_t w) : Word(w){}
  MySuperPuperUnion(uint8_t b1, uint8_t b2, uint8_t b3, uint8_t b4){
    Byte[0] = b1;
    Byte[1] = b2;
    Byte[2] = b3;
    Byte[3] = b4;
  }
  MySuperPuperUnion(uint16_t w1, uint16_t w2){
    HWord[0] = w1;
    HWord[1] = w2;
  }
};

const MySuperPuperUnion MyVal[3] = {
  MySuperPuperUnion(0x12,0x34, 0x56, 0x78),
  MySuperPuperUnion(0x1234,0x5678),
  MySuperPuperUnion(0x12345678),
};

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

3 hours ago, Darth Vader said:

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

может через asm как-то вывернуться (или вставка или отдельный модуль, или-или . . .), если "игра стоит свеч" и времени.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

3 часа назад, Darth Vader сказал:

Собственно, вопрос: а если мне надо/удобно инициализировать моё объединение по другому полю, неужели синтаксис языка этого не позволяет?

Сделать это поле первым? 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

7 часов назад, MegaVolt сказал:

Сделать это поле первым?

Не решает проблемы. В разных местах программы, для разных целей, мне удобно задавать значение разных полей объединения. Где-то слова, где-то массива из 4-х байт.

Что-то комитет по стандартизации С++ проворонил этот момент.

Конструкторы объединения - интересная идея.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

const WordUnion_t MyVal[3] = {
  {Byte: {0x12,0x34,0x12,0x34}},    // Это объединение инициализировано, как массив байт
  {HWord: {0x5678,0x1234}},         // Это объединение инициализировано, как массив полуслов
  {Word: 0x12345678}                // Это объединение инициализировано, как массив слов
};

А так?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

10 минут назад, adnega сказал:

А так?

Ух ты, круть. Я не знал про такое. Это только для объединений? (Для структур случайно не завезли? :-))

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Для структур тоже работает. Это gcc, не уверен, что везде так можно.

Так очень удобно задавать

int  rpm_arr_pos[RPM_NUM] = {[0 ... (RPM_NUM - 1)] = 0};

Не только массивы, но и массивы структур/объединений.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Ага, понял. Это gcc-шное расширение:

Цитата

warning: ISO C++ does not allow GNU designated initializers [-Wpedantic]

Полез искать информацию про это, обнаружил, что в c++20 designated initializers таки завезут, хотя и с некоторыми ограничениями.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

8 минут назад, adnega сказал:

Не только массивы, но и массивы структур/объединений.

А структуру из массивов так можно? Я тему такую создавал.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

20 минут назад, ViKo сказал:

А структуру из массивов так можно? Я тему такую создавал.

Думаю, это все не в духе С++ ;)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...