#c #unions
#c #профсоюзы
Вопрос:
t2 ниже вызывает следующую ошибку компиляции
test.cpp:14:15: error: cannot initialize a member subobject of type 'E' with an rvalue of type 'int'
Test t2{2, {{2, 3}}};
^
test.cpp:14:18: error: cannot initialize a member subobject of type 'void *' with an rvalue of type 'int'
Test t2{2, {{2, 3}}};
Как мне инициализировать второй набор? Возможно ли это, если я поменяю структуру и объединение местами?
enum E {
ea, eb, ec
};
struct Test {
int a;
union {
struct{E e; void*p; };
struct{int b, c; };
};
};
int main() {
Test t1{1, {{ea, 0}}};
Test t2{2, {{2, 3}}};
}
Комментарии:
1. C и объединения довольно сложны для правильной реализации. С C 17 —
std::variant
это решение, которое вы хотите.2. Я не думаю, что анонимные структуры являются кошерными в C . Там может быть какое-то странное поведение, но, предполагая GCC, вы, вероятно, получите C-подобное поведение.
3.
Test t2{2, {{2, 3}}};
преобразует anint
в anenum
и anint
в указатель. Оба не являются законными без гипса.. Это не имеет никакого отношения к союзу.4. @user4581301 C заставляет вас приводить целые числа к перечислениям, поэтому совместим только второй набор. Кроме того, целые числа также не преобразуются в void * автоматически
5. Приношу свои извинения за неясность. Именно это я и пытался донести до вас.
Ответ №1:
Это довольно просто, только первый (нестатический) член union
может быть инициализирован таким образом. Подробнее:
http://www.hellenico.gr/cpp/w/cpp/language/aggregate_initialization.html
Комментарии:
1. Ссылка выглядит как фрагмент cppreference. Вот прямая ссылка: en.cppreference.com/w/cpp/language/aggregate_initialization
2. Примечание: Если доступен C 20, вы можете использовать назначенные инициализаторы. Но не с анонимными структурами. С анонимными структурами в игре я не могу гарантировать, что в противном случае правильный ответ будет правильным. Такова боль от нестандартных расширений.