我有一个教程中的代码示例,
METHOD INTERCEPTOR AT SECOND Proxy
METHOD INTERCEPTOR AT FIRST Proxy
MAIN METHOD
我不知道为什么我们需要声明“ q”变量以及联合类型名称“ quantity”?为什么我们不能只放弃“数量”,然后通过点访问结构域?
更新:“ quantity”是工会类型的名称/标签,而“ q”不是变量而是工会成员/包含子成员(字段,数量,重量,卷)?
您不清楚该代码要问什么具体问题,所以让我们回顾一下这些问题。
当union
声明中出现struct
声明时,通常是声明该结构的成员为并集。该成员与其他任何成员一样都是结构的一部分,例如在结构中声明的int x
。结构的每个实例都包含其每个成员的实例,包括并集-并集是结构的一部分,而不是单独的东西。
在此代码中:
union quantity {
int count;
float weight,volume;
} q;
标识符quantity
是联合的标签。在此角色中,它必须出现在union
关键字之后,始终为union quantity
。它仅将联合命名为 type ;它没有命名结构的任何联合对象或成员。 (同一标识符可以在多个角色中使用。我们也可以也添加一个声明,该声明将quantity
定义为类型,对象或成员,然后它将具有两个角色:可以用作union quantity
来引用联合类型,也可以单独使用它来引用其他声明的声明。)
在上面的相同代码中,q
是结构成员的名称。 union quantity
的每个实例中的那个struct goods
对象的名称。
使用此声明,如果我们定义struct goods G;
,则G.q
指的是union quantity
中的G
和G.q.count
,{{1 }}和G.q.weight
引用联合G.q.volume
中的成员。 (一次只能存储其中一个成员,因为它们在一个联合中都重叠。)
在C 2011中,添加了一个新功能。一个G.q
或union
可以在另一个没有成员名称的structure
或union
中声明:
structure
这根本不会改变结构的布局,它仍然具有相同的成员。但是,它们的名称不同。给定一个struct goods {
char name[20];
union {
int count;
float weight,volume;
};
};
,我们可以将struct goods G
的成员称为count
而不是G.count
,对于G.q.count
和weight
也是类似的。 (请注意,除了删除成员名称volume
之外,此代码还删除了标签q
。C标准中有一条规则规定,要使结构或联合成为匿名,一定没有标签,也没有成员名称。我看不到技术上的原因。也许这是避免错误地删除成员名称的一种选择。)
关于为什么有人给工会成员一个名字而不是给它一个匿名的名字,原因是该代码写于2011年之前或2011年之后,但要在尚不支持匿名成员的C实现中使用。另一个原因是,他们想区分工会成员,因此任何人阅读或编写代码都将警惕这些成员位于结构内部的某个东西中,而不是常规的直接结构成员。
,我想不出为什么我们需要声明“ q”变量以及联合类型名称“ quantity”?
如问题中所述,struct goods
是具有两个成员的结构类型:由char
标识的20个name
数组和由{{1 }}(是的,union quantity
是一个联合标记,而不是成员的名称)。绝对没有必要以这种方式声明它,但是这样的声明提供了一些其他选择所没有的特征。但是请务必理解,如示例中所声明的,q
,quantity
和count
是weight
的 not 成员。相反,它们是volume
的成员,struct goods
是q
成员的联合。
为什么我们不能仅凭“数量”逃脱,然后通过点访问结构域?
因为这不是C语法提供的替代方法之一。在结构类型声明的成员列表中,联合标记(在这种情况下为struct goods
)只能出现在命名成员的声明中,因此,如果提供了该标记,则还必须声明联合的标识符-在示例中为quantity
。并且已将联合声明为已命名成员,则必须通过联合的标识符访问其成员。
另一方面,您可以省略标签,如果这样做,则可以选择省略联合的标识符。如果您确实省略了标识符(并且仅在这种情况下),那么您将拥有一个“匿名联合成员”,其访问本身的成员就像他们实际上是包含结构的成员一样。这非常接近您的要求。
请注意,无论如何,联合的成员彼此共享存储,因此联合在任何给定时间仅包含其中一个成员。它们不与包含结构的其他成员共享存储。
话虽如此,但各种选择的特征确实有所不同。首先,请务必理解所有这些形式都具有双重意义:它们声明联合 type ,并声明该类型的结构成员。这很重要,因为如果提供标签,那么无论联合声明在范围内如何,都可以声明相同联合类型的其他对象。而且,该范围不仅限于包含该范围的结构类型声明,因此使用所提供的声明,可以执行以下操作:
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
,尽管他们当中只有一个实际包含一个值,但即使您愿意承受这种效率低下,C也不提供保证以任何顺序进行操作都能可靠地达到预期的结果。