Структуры внутри союза - программирование

Структуры внутри союза

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"?

Какая разница создается с помощью {} вместо ()?

4b9b3361

Ответ 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}} };