Как использовать c union, вложенный в структуру без имени

Я работаю над так называемым проектом с открытым исходным кодом Hotspot, и, глядя на реализацию, я обнаружил неприятный вложенный союз в структуре, который выглядит следующим образом:

typedef struct RC_model_t_st
{
union
{
struct block_model_t_st *block;
struct grid_model_t_st *grid;
};
/* block model or grid model    */
int type;
thermal_config_t *config;
}RC_model_t;

Насколько я знаю в C / C ++, это объединение недопустимо. Итак, как кто-то может использовать объявленный таким образом союз и с какой целью?

Спасибо!

13

Решение

Это анонимный союз. В C ++, согласно [class.union], параграф 5:

Для поиска имени после определения анонимного объединения
Члены анонимного союза считаются определенными
в объеме, в котором объявлен анонимный союз

Это означает, что вы можете получить доступ к его членам, как если бы они были членами RC_model_t_st,

23

Другие решения

Не будучи уверенным и не попробовав:

Сам союз не доступен, но его члены.

Поэтому вы должны иметь возможность обратиться к obj.block а также obj.grid

8

Этот код здесь (https://gist.github.com/klange/4042963) показывает, как получить доступ к анонимным объединениям внутри структуры. Вы просто получаете доступ к членам вложенного объединения, как будто они являются членами структуры.

typedef struct {
union {
char * company;
char * school;
char * project;
};
union {
char * location;
char * url;
};
union {
char * title;
char * program;
};

time_t started;
time_t left;

char * description[];
} thing_t;

typedef thing_t job_t;

job_t yelp = {
.company  = "Yelp, Inc.",
.location = "San Francisco, CA",
.title    = "Software Engineer, i18n",
.started  = 1339977600,
.left     = CURRENT,
.description = {
"Developed several internal tools and libraries",
"Provided critical input and design work for Yelp's launch in Japan",
NULL
}
};
3

Имена, объявленные в анонимном объединении, используются напрямую, как переменные, не являющиеся членами.
Хорошая причина сделать это, чтобы сохранить память.

#include <iostream>

int main(int argc, char **argv) {
union {
double first;
double second;
};

first = 10.001;
second = 3.141592;
std::cout << first << " " << second << std::endl;

first = 10.002;
std::cout << first << " " << second << std::endl;
}
2

Чтобы развить ответ, предоставленный Анжью со ссылкой на стандарт, касающийся анонимных союзов и структур, я подумал предоставить образец исходного кода на C с выводом, сгенерированным этим образцом, показывающим, как значения распределяются внутри struct и union состоит из struct а также union компоненты.

Стандарт, цитируемый Angew:

Для поиска имени после определения анонимного объединения
Члены анонимного союза считаются определенными
в объеме, в котором объявлен анонимный союз.

Исходный код struct состоит из именованных и анонимных структур и союзов выглядит следующим образом. Это с использованием Visual Studio 2005 и #pragma (pack, 1) используется для выравнивания всего на char граница для того, чтобы не было дыр в памяти. Существует также простой макрос препроцессора C, определенный для того, чтобы сделать вывод более четким и легким для кодирования.

typedef unsigned char UCHAR;

// use of Microsoft Visual Studio pragma to force char alignment for the struct.
#pragma pack(push, 1)
const struct {
union {
const UCHAR myArray[];  // this array shares memory with struct following
struct {
const UCHAR iOne;
const UCHAR iTwo;
const UCHAR iThree;
};  // anonymous struct accessed by specifying Things.
};      // anonymous union accessed by specifying Things.
//  const UCHAR myArray[];   // will cause error - "error C2020: 'myArray' : 'struct' member redefinition"union {
const UCHAR myArray[];  // this array shares memory with struct following
struct {
const UCHAR iOne;
const UCHAR iTwo;
const UCHAR iThree;
} s;    // named struct accessed by specifying Things.u.s
} u;        // named union accessed by specifying Things.u
} Things = {1, 2, 4, 8, 9, 10, 22, 23, 24, 25};
#pragma pack(pop)

// a little helper macro to make the output easier to code.
#define PRINTF_VAL(x) printf ("%s %d \n", #x, x)

int itSelf (UCHAR iMask)
{
int iMatch = -1;

int jj = 0;
jj = Things.myArray[0]; PRINTF_VAL(Things.myArray[0]);
jj = Things.myArray[1]; PRINTF_VAL(Things.myArray[1]);
jj = Things.myArray[2]; PRINTF_VAL(Things.myArray[2]);
jj = Things.myArray[3]; PRINTF_VAL(Things.myArray[3]);
jj = Things.myArray[4]; PRINTF_VAL(Things.myArray[4]);
jj = Things.iOne; PRINTF_VAL(Things.iOne);
jj = Things.iTwo; PRINTF_VAL(Things.iTwo);
jj = Things.iThree; PRINTF_VAL(Things.iThree);

jj = Things.u.myArray[0]; PRINTF_VAL(Things.u.myArray[0]);
jj = Things.u.myArray[1]; PRINTF_VAL(Things.u.myArray[1]);
jj = Things.u.myArray[2]; PRINTF_VAL(Things.u.myArray[2]);
jj = Things.u.myArray[3]; PRINTF_VAL(Things.u.myArray[3]);
jj = Things.u.myArray[4]; PRINTF_VAL(Things.u.myArray[4]);
jj = Things.u.s.iOne; PRINTF_VAL(Things.u.s.iOne);
jj = Things.u.s.iTwo; PRINTF_VAL(Things.u.s.iTwo);
jj = Things.u.s.iThree; PRINTF_VAL(Things.u.s.iThree);

return iMatch + 1;
}

Вывод, сгенерированный этой функцией, выглядит следующим образом:

Things.myArray[0] 1
Things.myArray[1] 2
Things.myArray[2] 4
Things.myArray[3] 8
Things.myArray[4] 9
Things.iOne 1
Things.iTwo 2
Things.iThree 4
Things.u.myArray[0] 8
Things.u.myArray[1] 9
Things.u.myArray[2] 10
Things.u.myArray[3] 22
Things.u.myArray[4] 23
Things.u.s.iOne 8
Things.u.s.iTwo 9
Things.u.s.iThree 10

Выходные данные показывают перекрытие между различными компонентами основного struct, Things вызвано использованием союзов. Вы также можете увидеть, как компоненты анонимного struct а также union ссылаются по сравнению с теми компонентами названного struct а также union,

Также просто для удовольствия я попытался добавить определение массива const UCHAR myArray[]; после анонимного union содержащий const UCHAR myArray[]; чтобы увидеть, что произойдет. Компилятор пожаловался на ошибку error C2020: 'myArray' : 'struct' member redefinition, Дополнение закомментировано в struct значение Things выше. Однако со второго использования const UCHAR myArray[]; находится в названном union компиляция работает, потому что второе использование доступно путем указания имени объединения.

2

Прежде всего я хочу сказать, что Объединение — это набор переменных разных типов, как и структура. Однако в случае союзов вы можете одновременно хранить информацию только в одном поле.

Союзы в основном используются для экономии памяти & его размер равен наибольшему члену союза.

А для доступа к полям данных объединения используйте оператор точки (.) Точно так же, как для структуры, что объясняется @Atmocreations. Когда значение присваивается одному члену, другие члены извлекаются, поскольку они совместно используют одну и ту же память.

В качестве примера, где союзы могут быть полезны

union time
{
long time_in_sec;
double time_in_mili_sec;
}mytime;

….
Вышеуказанное объединение можно использовать для хранения текущего времени (в секундах) для сохранения времени с точностью до секунды. Или это может быть использовано для удержания времени с точностью до миллисекунды. Предположительно, бывают моменты, когда вы захотите одно или другое, но не оба. Эта декларация должна выглядеть знакомой. Это то же самое, что и определение структуры, но с ключевым словом union вместо struct.

для получения дополнительной информации http://msdn.microsoft.com/en-us/library/5dxy4b7b(v=vs.80).aspx

-3