Как использовать C union, вложенный в struct без имени
Я работаю над так называемым проектом с открытым исходным кодом Hotspot, и, глядя на реализацию, я нашел неприятный вложенный Союз в struct, выглядящий так:
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/" class="blnk">C / C++, этот союз непостижим. Так как же кто-то может использовать объявленный таким образом союз и с какой целью?
спасибо!
6 ответов
прежде всего я хочу сказать, что объединение-это набор переменных разных типов, как и структура. Однако с помощью unions вы можете хранить информацию только в одном поле в любой момент времени.
союзы в основном используются для сохранения памяти & его размер равен самому большому члену Союза.
и для доступа к полям данных объединения используйте оператор точки(.) так же, как для структуры и объясняется @Atmocreations. Когда значение назначается одному члену, другой член(ы) извлекается, так как они имеют одну и ту же память.
в качестве примера, где союзы могут быть полезны, является
union time    
        {
        long time_in_sec;
        double time_in_mili_sec;
        }mytime;
.... Объединение выше может использоваться для хранения текущего времени (в секундах), чтобы удерживать время с точностью до секунды. Или его можно использовать, чтобы удерживать время с точностью до миллисекунды. По-видимому, бывают моменты, когда вы хотели бы одного или другого, но не оба. Это заявление должно выглядеть знакомым. Это то же самое, что и определение структуры, но с ключевым словом union вместо struct.
дополнительная информация http://msdn.microsoft.com/en-us/library/5dxy4b7b(в=против 80).аспн
Это анонимный Союз. В C++, согласно [class.союза], пункт 5:
для поиска имени после определения анонимного объединения, члены анонимного Союза считаются определенными в области, в которой объявлен анонимный Союз
Это означает, что вы можете получить доступ к его членам, как если бы они были членами RC_model_t_st.
не будучи уверенным и не попробовал:
сам союз недоступен, но его члены есть.
поэтому вы должны иметь возможность ссылаться на obj.block и obj.grid
этот код здесь (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
    }
};
имена, объявленные в анонимном объединении, используются напрямую, как переменные, не являющиеся членами. Хорошая причина сделать это-сохранить память.
#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;
}
чтобы уточнить ответ, предоставленный Angew, цитируя стандарт, касающийся анонимных союзов и структур, я думал предоставить образец исходного кода C с выводом, генерируемым этим образцом, показывающим, как значения распределяются в A 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
выход показывает перекрытие между различными компонентами main struct, Things вызвано использованием союзов. Вы также можете увидеть, как компоненты anonymous struct и union ссылаются по сравнению с этими компонентами именованного struct и union.
также просто для удовольствия я попытался добавить определение массива const UCHAR myArray[]; после анонимного union содержащий const UCHAR myArray[]; чтобы увидеть, что произойдет. Компилятор пожаловался на ошибку error C2020: 'myArray' : 'struct' member redefinition. Добавление прокомментировано в struct определение Things выше. Однако со второго использования const UCHAR myArray[]; в имя union компиляция работает, потому что второе использование доступно, указав имя объединения.