匿名联盟的目的是什么?

What is the purpose of Anonymous Unions?

通过在结构中声明匿名联合,您可以直接访问成员。这是有道理的,我想,就像一个普通的联合,你只能从最近写入的值中读取。 Then I saw this

#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" 范围内声明变量?

您可以不同地解释相同的内存段。它广泛用于协议实现。在您接收字节缓冲区的地方,并根据需要根据各种标志treat/decode接收它。

在此示例中,int 和 char 的大小和字节顺序不同

根据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;
}; 

现在您可以以 obj.numobj.num_byte[i] 的身份访问 struct Scope 成员。在内存中的联合之后,将有一个不同的变量 foo,因此显然联合成员无法移出结构。

如果不是匿名联合,我们将不得不输入类似 obj.name.num 的内容,其中的名称可能很混乱。


关于读取不同的联合成员,你的说法"you could only read from the most recent value that has been written to"在C中是不正确的。注意这里C和C++是不同的。

C17 6.5.2.3 声明:

A postfix expression followed by the . operator and an identifier designates a member of a structure or union object. The value is that of the named member,95) and is an lvalue if the first expression is an lvalue.

脚注 95) 有帮助的地方:

95) If the member used to read the contents of a union object is not the same as the member last used to store a value in the object, the appropriate part of the object representation of the value is reinterpreted as an object representation in the new type as described in 6.2.6 (a process sometimes called ‘‘type punning’’). This might be a trap representation.

6.2.6中脚注所指的部分:

When a value is stored in a member of an object of union type, the bytes of the object representation that do not correspond to that member but do correspond to other members take unspecified values.

Where an operator is applied to a value that has more than one object representation, which object representation is used shall not affect the value of the result. Where a value is stored in an object using a type that has more than one object representation for that value, it is unspecified which representation is used, but a trap representation shall not be generated.

用简单的英语来说,这意味着 C 允许类型双关,但程序员有责任确保它在 alignment/padding、陷阱表示、字节顺序等方面是可行的。