union 这种行为背后的逻辑是什么?
What is the logic behind this behavior in union?
我声明了一个包含 2 个结构的联合,并为每个元素赋值,然后打印它们。
union data {
struct s1 {
int a;
int b;
}c;
struct s2 {
int d;
int e;
}f;
} x;
/* Assignment */
x.c.a=1;
x.f.e=2;
x.c.b=3;
x.f.d=4;
printf("%d %d %d %d\n", x.c.a, x.f.e, x.c.b, x.f.d);
它的输出是这样的 -> 4 3 3 4
但是,当我按以下顺序分配值时 ->
x.c.b=3;
x.f.d=4;
x.c.a=1;
x.f.e=2;
它的输出是这样的 -> 1 2 2 1
这种变化背后的逻辑是什么??
为了了解发生了什么,您需要回想一下 union
成员共享相同的内存。在你的例子中,union
有两个成员:一个叫做 c
,另一个叫做 f
。
对 c
成员的任何赋值都会更改 f
成员的内容,反之亦然。在你的例子中,两个成员的结构是相同的,以下对共享相同的 space:
x.c.a / x.f.d
x.c.b / x.f.e
该对中的一个成员的任何赋值都会导致该对中的另一个成员也更改其值。这正是您看到的行为:每对的两个成员都具有相同的值,等于上次赋值的值。
A union
有足够的 space 来存储其最大的成员。在您的情况下,两个成员的大小相同。 x
的内存布局可以容纳两个 int
。
x.c.a=1; // Sets the value of the first int to 1
x.f.e=2; // Sets the value of the second int to 2
x.c.b=3; // Sets the value of the second int to 3
x.f.d=4; // Sets the value of the first int to 4
在这些语句的末尾,第一个 int
中有 3
,第二个 int
中有 4
。
printf("%d %d %d %d\n", x.c.a, x.f.e, x.c.b, x.f.d);
相当于:
int i1 = x.c.a; // i1 is 4
int i2 = x.c.b; // i2 is 2
printf("%d %d %d %d\n", i1, i2, i2, i1);
产生输出 4 3 3 4
。
当您使用时:
x.c.b=3; // Sets the value of the second int to 3
x.f.d=4; // Sets the value of the first int to 4
x.c.a=1; // Sets the value of the first int to 1
x.f.e=2; // Sets the value of the second int to 2
在这些语句的末尾,第一个 int
中有 1
,第二个 int
中有 2
。
这解释了第二个输出。
您可能已经知道这一点,但是 union
s 在同一数据块上指定了多个视图。您恰好指定了两个相同的视图(两个 int
的结构)。
因此,您的两个分配序列可以分别重写为:
x.c.a=1;
x.c.b=2;
x.c.b=3;
x.c.a=4;
和
x.c.b=3;
x.c.a=4;
x.c.a=1;
x.c.b=2;
.
在第一种情况下,最后对x.c.a
和x.c.b
的赋值分别是4
和3
,所以它们仍然存在。在第二种情况下,它们是 1
和 2
,因此它们反映在输出中。
我声明了一个包含 2 个结构的联合,并为每个元素赋值,然后打印它们。
union data {
struct s1 {
int a;
int b;
}c;
struct s2 {
int d;
int e;
}f;
} x;
/* Assignment */
x.c.a=1;
x.f.e=2;
x.c.b=3;
x.f.d=4;
printf("%d %d %d %d\n", x.c.a, x.f.e, x.c.b, x.f.d);
它的输出是这样的 -> 4 3 3 4
但是,当我按以下顺序分配值时 ->
x.c.b=3;
x.f.d=4;
x.c.a=1;
x.f.e=2;
它的输出是这样的 -> 1 2 2 1
这种变化背后的逻辑是什么??
为了了解发生了什么,您需要回想一下 union
成员共享相同的内存。在你的例子中,union
有两个成员:一个叫做 c
,另一个叫做 f
。
对 c
成员的任何赋值都会更改 f
成员的内容,反之亦然。在你的例子中,两个成员的结构是相同的,以下对共享相同的 space:
x.c.a / x.f.d
x.c.b / x.f.e
该对中的一个成员的任何赋值都会导致该对中的另一个成员也更改其值。这正是您看到的行为:每对的两个成员都具有相同的值,等于上次赋值的值。
A union
有足够的 space 来存储其最大的成员。在您的情况下,两个成员的大小相同。 x
的内存布局可以容纳两个 int
。
x.c.a=1; // Sets the value of the first int to 1
x.f.e=2; // Sets the value of the second int to 2
x.c.b=3; // Sets the value of the second int to 3
x.f.d=4; // Sets the value of the first int to 4
在这些语句的末尾,第一个 int
中有 3
,第二个 int
中有 4
。
printf("%d %d %d %d\n", x.c.a, x.f.e, x.c.b, x.f.d);
相当于:
int i1 = x.c.a; // i1 is 4
int i2 = x.c.b; // i2 is 2
printf("%d %d %d %d\n", i1, i2, i2, i1);
产生输出 4 3 3 4
。
当您使用时:
x.c.b=3; // Sets the value of the second int to 3
x.f.d=4; // Sets the value of the first int to 4
x.c.a=1; // Sets the value of the first int to 1
x.f.e=2; // Sets the value of the second int to 2
在这些语句的末尾,第一个 int
中有 1
,第二个 int
中有 2
。
这解释了第二个输出。
您可能已经知道这一点,但是 union
s 在同一数据块上指定了多个视图。您恰好指定了两个相同的视图(两个 int
的结构)。
因此,您的两个分配序列可以分别重写为:
x.c.a=1;
x.c.b=2;
x.c.b=3;
x.c.a=4;
和
x.c.b=3;
x.c.a=4;
x.c.a=1;
x.c.b=2;
.
在第一种情况下,最后对x.c.a
和x.c.b
的赋值分别是4
和3
,所以它们仍然存在。在第二种情况下,它们是 1
和 2
,因此它们反映在输出中。