Я не могу понять, зачем нам объявлять переменную 'q' вместе с именем типа объединения 'количество'?
Как указано в вопросе, struct goods
- это тип структуры с двумя членами: массив из 20 char
, обозначенный name
, и union quantity
, обозначенный q
(так что да, quantity
является тегом объединения, а не именем члена). Нет необходимости в абсолютном смысле декларировать это таким образом, но такое объявление предоставляет несколько характеристик, которых нет у других альтернатив. Однако поймите, что, как заявлено в примере, count
, weight
и volume
являются , а не членами struct goods
. Скорее, они являются членами q
, союза, который является членом struct goods
.
Почему мы не можем получить просто «количество» и затем получить доступ к полям структуры через точку?
Потому что это не одна из альтернатив, которые предоставляет синтаксис C. В списке членов объявления типа структуры тег объединения (quantity
в данном случае) может появляться только в объявлении члена с именем , поэтому, если это предусмотрено, вы также должны объявить идентификатор для объединения - q
в примере. И объявив объединение в качестве именованного члена, вы должны получить доступ к его членам через идентификатор объединения.
С другой стороны, вы можете опустить тег, и если вы это сделаете, то При желании вы также можете опустить идентификатор объединения. Если вы опускаете идентификатор (и только в этом случае), у вас есть «анонимный член объединения», чьи собственные члены доступны , как если бы они действительно были членами содержащей структуры. Это очень близко к тому, о чем вы спрашиваете.
Обратите внимание, что в любом случае члены объединения делят хранилище друг с другом, поэтому союз содержит только одного из них в любой момент времени. Они не разделяют хранилище с другими членами вмещающей структуры.
При этом различные варианты имеют некоторые различия в своих характеристиках. Прежде всего, оцените, что все эти формы имеют двоякое значение: они объявляют объединение тип , и они объявляют член структуры этого типа. Это важно, потому что если вы предоставите тег, вы можете объявить другие объекты того же типа объединения, где бы ни было объявление объединения. Кроме того, эта область не ограничивается объявлением типа структуры, которое содержит его, поэтому с представленной декларацией можно сделать что-то вроде этого:
void set_quantity(struct goods *g, union quantity quant) {
g->q = quant;
}
Это невозможно для нетегированных объединений.
Существует также, по крайней мере, одно важное различие между именованным членом с нетегированным типом объединения и анонимным членом объединения: вы можете получить доступ к самому объединению, только если он назван. Примите во внимание следующее:
struct goods2 {
char name[20];
union {
int count;
float weight, volume;
} q;
};
void copy_quantity(struct goods2 *dest, struct goods2 *src) {
dest->q = src->q;
}
Мало того, что вы не можете сделать это с анонимным членом профсоюза, вы не можете сделать что-либо надежно эквивалентное. В частности, даже если вы готовы испытать неэффективность, связанную с копированием src->count
, src->weight
и src->volume
по отдельности, несмотря на то, что только один из них действительно содержит значение, C не дает никаких обещаний, что при этом в любом порядке позволит надежно достичь желаемого результата.