[英]What is the purpose of Anonymous Unions?
通过在结构中声明匿名联合,您可以直接访问成员。 这是有道理的,我想,就像一个普通的联合,你只能从最近写入的值中读取。 然后我看到了这个
#include<stdio.h>
struct Scope
{
// Anonymous union
union
{
char alpha;
int num;
};
};
int main()
{
struct Scope x;
x.num = 65;
// Note that members of union are accessed directly
printf("x.alpha = %c, x.num = %d", x.alpha, x.num);
return 0;
}
那么,如果我可以一直访问所有变量,那有什么意义呢? 为什么不只在“Scope”范围内声明变量?
根据C11 6.2.6.1 ,被访问成员的值是未指定的。 一般来说,它可能是一个陷阱表示,它会触发未定义的行为。
(如果您将char
更改为unsigned char
,那将是安全的,因为unsigned char
不能具有陷阱表示。因此您的程序将运行完成并打印一些内容,但 C 标准没有指定将为x.alpha
打印什么值。 )
当然,任何给定的实现都可以指定您实际获得的值(例如x.num
的低字节或高字节)。 因此,此类代码很可能仅适用于此类实现,并不意味着可移植或符合标准。
正如彼得指出的那样,所有这些都与您使用匿名联合还是老式联合无关。
关键是struct Scope
可以有其他成员。 一个更现实的例子:
struct Scope
{
union
{
int num;
uint8_t num_byte [sizeof(int)];
};
int foo;
};
现在您可以访问struct Scope
成员作为obj.num
或obj.num_byte[i]
。 在内存中的联合之后,将会有一个不同的变量foo
,所以很明显联合成员不能移到结构中。
如果不是匿名联合,我们必须输入类似obj.name.num
,其中 name 可能只是混乱。
关于读取不同的联合成员,您的陈述“您只能从已写入的最新值中读取”在 C 中不正确。请注意,C 和 C++ 在这里是不同的。
C17 6.5.2.3 规定:
后缀表达式后跟 . 运算符和标识符指定结构或联合对象的成员。 该值是命名成员的值,95) 并且如果第一个表达式是左值则是左值。
脚注 95) 有帮助的地方:
95) 如果用于读取联合对象内容的成员与上次用于在对象中存储值的成员不同,则将该值的对象表示的适当部分重新解释为新对象中的对象表示类型如 6.2.6 中所述(有时称为“类型双关语”的过程)。 这可能是一个陷阱表示。
脚注所指的6.2.6部分:
当值存储在联合类型对象的成员中时,不对应于该成员但对应于其他成员的对象表示的字节采用未指定的值。
当运算符应用于具有多个对象表示的值时,使用哪种对象表示不应影响结果的值。 当一个值存储在一个对象中,该类型使用具有多个对象表示的类型,未指定使用哪种表示,但不应生成陷阱表示。
通俗地说,这意味着 C 允许类型双关,但程序员有责任确保它在对齐/填充、陷阱表示、字节序等方面是可行的。
您可以不同地解释相同的内存段。 它广泛用于协议实现。 您在哪里接收字节缓冲区并根据各种标志根据需要对其进行处理/解码。
在这个例子中 int 和 char 是不同的大小和字节顺序
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.