Структуры внутри союза
int main()
{
union {
struct {
char c[2];
char ch[2];
} s;
struct {
int i;
int j;
} st;
} u = { (12, 1), (15, 1) };
printf("%d %d ", u.st.i, u.st.j);
}
Как вышло выше, это "257 0"?
Какая разница создается с помощью {}
вместо ()
?
Ответы
Ответ 1
Оба (12, 1)
и (15, 1)
упрощают (как это ни странно) 1
. Это потому, что, как сказал Омкант, вы используете оператор запятой, который выполняет каждое деление, которое он делит, но возвращает значение окончательного выражения. Wikipedia entry действительно объясняет это довольно хорошо.
В результате u.s.c[0]
заполняется первым 1 и u.s.c[1]
заполняется вторым 1. Так как объединение перекрывает int u.st.i
над u.c[2]
и u.ch[2]
(предполагая 8-битные символы и 32-битные ints), а архитектура малозначна (известна из вашего результата), у вас есть 1 в младшем байте u.st.i
и 1 во втором младшем байте для значения 256*1 + 1 = 257
.
Между тем в память u.st.j
не было записано никаких значений, поэтому второй вывод равен 0.
Ответ 2
{}
означает инициализацию под-объекта.
()
- оператор, который группирует выражение, например. (1+3)*2
. Вы смутно использовали оператор запятой, который отбрасывает левый операнд и возвращает правый операнд. (12,1)
совпадает с 1
.
Инициализация a union
всегда устанавливает свой первый член и игнорирует остальные. Это связано с тем, что только один элемент за один раз может сохранить значение.
Инициализация подобъекта массива со скалярным значением, так как при передаче 1
для инициализации c[2]
автоматически переходит в массив. Это называется фигурной скобкой. Следующий 1
инициализирует второй элемент массива.
Вы назначили 1
каждому из символов в c[2]
, а затем верните результирующую строку байта в качестве малознакового int
. Массив ch[2]
не был явно инициализирован; в С++ он будет установлен на ноль, но я не совсем уверен в C.
Инициализатор { {12, 1}, {15, 1} }
не работает, потому что, по-видимому, привязка elision интерпретирует первый }
для закрытия всего union
.
Инициализатор {{ {12, 1}, {15, 1} }}
будет избегать выравнивания и установить оба массива. { 12, 1, 15, 1 }
должен сделать то же самое.
Обратите внимание, что преобразование между скалярными значениями и байтовыми строками определяется реализацией; в частности, это зависит от степени и размера int
.
Ответ 3
what the difference will it create if i use {} instead of ().
Если вы используете ()
, тогда ,
будет Comma operator
, и назначенное значение будет иметь самое правое значение в скобках.
Но в случае {}
,
есть Comma seperator
, и каждому отдельному значению присваиваются соответствующие члены. Но в этом случае он не компилируется и не выдает ошибку:
extra brace group at end of initializer.
Ответ 4
Кажется, вы неправильно понимаете смысл союзов, объекты в профсоюзах делятся своей памятью, поэтому вы можете инициализировать один из объектов не только обоими, другими словами, базовая память одинакова, и, как упоминалось в другом ответе, инициализируя объединение всегда устанавливает свой первый член, поэтому, если вы хотите инициализировать второй член, вы можете использовать назначенные инициализаторы C99:
u = {.st={15, 1} };
И для инициализации массивов в первой структуре:
u = { .s={{12, 1}, {15, 1}} };
Или без .s
для первой структуры:
u = { {{12, 1}, {15, 1}} };