Darth Vader 0 19 июля, 2020 Опубликовано 19 июля, 2020 · Жалоба В Си можно сделать так: #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. Собственно, вопрос: а если мне надо/удобно инициализировать моё объединение по другому полю, неужели синтаксис языка этого не позволяет? Странное впечатление создается. Язык большой, развесистый, позволяет сделать кучу всего несколькими разными способами, а такого простого действия, как инициализации нужного поля объединения - не позволяет. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AHTOXA 18 19 июля, 2020 Опубликовано 19 июля, 2020 · Жалоба Да, это почти единственная сишная фишка, которой мне не хватает в плюсах. Конкретно в этом случае можно выкрутиться, написав конструкторы для объединения: 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), }; Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
k155la3 27 19 июля, 2020 Опубликовано 19 июля, 2020 · Жалоба 3 hours ago, Darth Vader said: . . . Странное впечатление создается. Язык большой, развесистый, позволяет сделать кучу всего несколькими разными способами, а такого простого действия, как инициализации нужного поля объединения - не позволяет. может через asm как-то вывернуться (или вставка или отдельный модуль, или-или . . .), если "игра стоит свеч" и времени. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
MegaVolt 29 19 июля, 2020 Опубликовано 19 июля, 2020 · Жалоба 3 часа назад, Darth Vader сказал: Собственно, вопрос: а если мне надо/удобно инициализировать моё объединение по другому полю, неужели синтаксис языка этого не позволяет? Сделать это поле первым? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Darth Vader 0 20 июля, 2020 Опубликовано 20 июля, 2020 · Жалоба 7 часов назад, MegaVolt сказал: Сделать это поле первым? Не решает проблемы. В разных местах программы, для разных целей, мне удобно задавать значение разных полей объединения. Где-то слова, где-то массива из 4-х байт. Что-то комитет по стандартизации С++ проворонил этот момент. Конструкторы объединения - интересная идея. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
adnega 11 20 июля, 2020 Опубликовано 20 июля, 2020 · Жалоба const WordUnion_t MyVal[3] = { {Byte: {0x12,0x34,0x12,0x34}}, // Это объединение инициализировано, как массив байт {HWord: {0x5678,0x1234}}, // Это объединение инициализировано, как массив полуслов {Word: 0x12345678} // Это объединение инициализировано, как массив слов }; А так? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AHTOXA 18 20 июля, 2020 Опубликовано 20 июля, 2020 · Жалоба 10 минут назад, adnega сказал: А так? Ух ты, круть. Я не знал про такое. Это только для объединений? (Для структур случайно не завезли? :-)) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
adnega 11 20 июля, 2020 Опубликовано 20 июля, 2020 · Жалоба Для структур тоже работает. Это gcc, не уверен, что везде так можно. Так очень удобно задавать int rpm_arr_pos[RPM_NUM] = {[0 ... (RPM_NUM - 1)] = 0}; Не только массивы, но и массивы структур/объединений. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AHTOXA 18 20 июля, 2020 Опубликовано 20 июля, 2020 · Жалоба Ага, понял. Это gcc-шное расширение: Цитата warning: ISO C++ does not allow GNU designated initializers [-Wpedantic] Полез искать информацию про это, обнаружил, что в c++20 designated initializers таки завезут, хотя и с некоторыми ограничениями. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 20 июля, 2020 Опубликовано 20 июля, 2020 · Жалоба 8 минут назад, adnega сказал: Не только массивы, но и массивы структур/объединений. А структуру из массивов так можно? Я тему такую создавал. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
adnega 11 20 июля, 2020 Опубликовано 20 июля, 2020 · Жалоба 20 минут назад, ViKo сказал: А структуру из массивов так можно? Я тему такую создавал. Думаю, это все не в духе С++ ;) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться