#include <stdio.h>
#include <stdlib.h>
union IFC {
int i;
float f;
char c;
};
int main(void) {
union IFC ifc = {.f = 3.14};
printf("Union's float is %.2f\n", ifc.f); // 3.14
ifc.i = 2;
printf("Union's integer is %d\n", ifc.i); // 2
ifc.c = 'A';
printf("Union's character is %c\n", ifc.c); // A
printf("Union's float is %.2f\n", ifc.f); // 0.00
return 0;
}
此代码如何在计算机内存级别工作?联合使用时0.00y的值从何而来?我知道一个联合在任何允许的状态下(在我的情况下/ / )占用相同的字节数。但是这些字节只存储一个值。为什么,如果符号“A”当前存储在那里,我仍然可以参考联合来获取实数吗?虽然它不是我曾经问过的,虽然它总是等于零,但它仍然返回。这个怎么运作?inf.finf.cintfloatcharinf.f
所有字段的位占用相同的内存。
它们的解释取决于您正在访问的字段的名称(类型)。
那。通过更改任何字段,您可以同时更改所有其他字段。
首先,C语言保证一个union的所有字段都具有相同的地址,即与整个union的地址相同。实际上,这意味着所有联合字段都重叠存储在同一内存地址。联合的大小将等于其最大字段的大小(加上可能为对齐目的而添加的一些额外未使用的字节)。
其次,C 语言表示,将值分配给联合的某个字段会使该字段中未使用的字节处于不确定状态。出于这个原因,由于
char c您平台上的 field 可能小于 field ,因此在为该字段分配值后float f读取该字段是没有意义的- 这通常会导致未定义的行为。在实践中,可以合理地假设即使在同一个程序中,一个值的条目可以影响联合的所有字节,而另一个只影响联合本身的字节。fcccC 中的 Union 可用于将一种类型的对象表示重新解释为另一种类型的对象表示,但这通常只对相同大小的类型有意义。
一个简单的 GCC 实验表明(https://godbolt.org/z/nphzx-)在未优化的代码中,您的联合存储在内存中,更改字段值
c只会更改一个字节的内存,但在优化的代码中,整个联合是存储在处理器寄存器中esi并写入字段值c会覆盖寄存器的全部内容,即 实际上重置所有“额外”联合字节。联合体通常用于与硬件一起工作——读取、检查和写入每个字的位。假设您正在为需要使用该设备上的多个寄存器的设备编写驱动程序,并且每个寄存器都是一组多个位字段。最简单的方法是:
然后,您可以使用字长字段 ( xyz.int_value )读取/写入寄存器值,并使用位字段 ( xyz.bit_fields.field2 ) 处理位。
这是一个非常清晰的图表。
内存布局: