Союзы в союзах - PullRequest
       10

Союзы в союзах

6 голосов
/ 29 сентября 2010

В C возможно ли определить объединение в другом объединении?Если нет, то почему это невозможно?Или, если да, где его можно использовать?

Ответы [ 5 ]

6 голосов
/ 29 сентября 2010

Предположим, вы хотите определить:

union myun {
  int x;
  sometype y;
};

, где sometype - это typedef, определяемое используемой вами библиотекой.Если бы библиотека реализовала его как объединенный тип, то это было бы объединение внутри объединения, и это имело бы смысл, потому что вы не можете (с хорошей точки зрения разработки) нарушить инкапсуляцию типа библиотеки.

3 голосов
/ 29 сентября 2010

Да, это возможно и полезно.Причина та же самая причина X в Y полезна для многих значений X и Y: композиционность.Программы создаются путем объединения крошечных компонентов в маленькие компоненты в более крупные компоненты в огромные компоненты в ... Иногда случается, что кучка союзов собирается в объединение, и что с того?

R .. 'Ответ s показывает пример, где это происходит за кулисами: просто случается, что один из типов членов объединения является объединением, но вы не узнаете об этом, если не посмотрите на реализацию библиотеки.


EDIT Однако обратите внимание, что общая идиома для дискриминируемых объединений, где каждый член объединения является структурой, первое поле которой является целочисленным типом, содержащим тег, не распространяется на вложенные объединения.Таким образом, ниже приводится стандартная ( N1256 §6.5.2.3.5) реализация дискриминационных объединений в C:

struct generic {
    unsigned tag;
};
struct smallnum {
    unsigned tag; /*always TAG_SMALLNUM*/
    unsigned value;
};
struct bignum {
    unsigned tag; /*always TAG_BIGNUM*/
    size_t length;
    unsigned *p;
};
struct string {
    unsigned tag; /*always TAG_STRING*/
    size_t length;
    char *p;
};
union number {
    struct bignum bignum;
    struct smallnum smallnum;
};
union object {
    struct generic generic;
    struct bignum bignum;
    struct smallnum smallnum;
    struct string string;
};

Если у вас есть union objectобъект x, вы всегда можете прочитать его тег как x.generic.tag (или x.bignum.tag или любой другой), независимо от того, что на самом деле было присвоено объекту.Используя уникальные теги (дискриминаторы) для объектов.

Следующее определение является допустимым, но бесполезным, так как вы не можете просто прочитать первое поле объекта union level2, чтобы получить тег: if union level2объект был записан как union number, вы должны прочитать его тег через член number, в противном случае вы должны прочитать его тег через член generic или string.Я не удивлюсь, если доступ через неправильный член сработает в каждой существующей реализации, но он не соответствует стандартам.

union level2 {
    struct generic generic;
    union number number;
    struct string string;
};
2 голосов
/ 29 сентября 2010

Да, это возможно. Но я склонен придерживаться совета никогда не использовать союзы. Количество ситуаций, когда профсоюзы являются правильным ответом, очень мало. Я подозреваю, что нет такой ситуации, когда профсоюз, содержащий профсоюз, является хорошей идеей.

1 голос
/ 29 сентября 2010

Да, это возможно. Я не могу придумать, как правильно использовать макушку головы, хотя было бы легко придумать надуманный пример.

0 голосов
/ 29 сентября 2010

Да, союз может содержать другой союз:

union foo {
  int x;
  double y;
  union bar {
    char blah[10];
    char *blurga;
  } bletch;
};

Я не могу вспомнить ситуацию, когда это было бы полезно (или даже желательно), хотя.

...