C语言编程中的结构与并集

C语言编程中的结构与并集,c,structure,printf,status,unions,C,Structure,Printf,Status,Unions,我不确定Status的Printf语句会打印什么?我猜它是依赖于编译器的,有人能解释一下最后设置的Status会打印什么吗 #include <stdio.h> #include <string.h> typedef union { struct { unsigned char colour; struct { unsigned char contrast :1; unsigned char density :3; unsig

我不确定Status的Printf语句会打印什么?我猜它是依赖于编译器的,有人能解释一下最后设置的Status会打印什么吗

#include <stdio.h>
#include <string.h>

typedef union {
 struct {
   unsigned char colour;
   struct {
     unsigned char contrast :1;
     unsigned char density :3;
     unsigned char depth :1;
     unsigned char brightness :1;
     unsigned char saturation :1;
     unsigned char channel :1;
 } bits;
} XStruct;


  unsigned short status;
} XUnion;


void main(void) {
 XUnion yunion;

 memset(&yunion, 0x00, sizeof(yunion));

 yunion.XStruct.contrast = 0xAE;
 yunion.XStruct.bits.density = 0x01;
 yunion.XStruct.bits.depth = 0x02;
 yunion.XStruct.bits.saturation = 0x01;

 printf("Status: %d", yunion.status);
}
#包括
#包括
typedef联合{
结构{
无符号字符颜色;
结构{
无符号字符对比度:1;
无符号字符密度:3;
无符号字符深度:1;
无符号字符亮度:1;
无符号字符饱和度:1;
无符号字符通道:1;
}比特;
}X结构;
无符号短状态;
}徐宁;
真空总管(真空){
徐宁·尤宁;
memset(&yunion,0x00,sizeof(yunion));
yunion.XStruct.contrast=0xAE;
yunion.XStruct.bits.density=0x01;
yunion.XStruct.bits.depth=0x02;
yunion.XStruct.bits.saturation=0x01;
printf(“状态:%d”,yunion.Status);
}

联合可以有多个数据类型的变量,但您只能为其中一个指定值

为一个变量赋值并打印另一个变量时会发生什么情况?

为了便于计算,可以将并集视为从地址0开始的内存块。此内存块的大小是此联合中使用的最大数据类型的大小。在您的情况下,它将是
结构

因此,当你给联合体中的变量赋值时,你就是在这个块中“放入”值。当您打印这些成员中的任何一个时,它将打印从联合开始到您打印的成员的数据类型大小的块内容

在本例中,您已经打印了变量
status
。现在,在我的系统上
unsigned short
使用2字节的存储空间。所以在我的系统中,它会在赋值后打印联合的前两个字节。在像您那样分配值之后,此内存块的前两个字节如下所示:

    0100 0101 1010 1110
因此,当我在我的机器上打印
status
时,它以十进制打印
0x45ae
17838
。因此,根据
sizeof(unsigned short)

使用该代码,更改指定的值以注意输出中的差异。这样你会理解得更快

更新:

位字段的顺序取决于目标平台的端度。看看这个:

然后,这个:

考虑到这一点,下面是对您的位字段的分解:

    1                 010    00     1       0
   line_current_on   flags1     battery_ok
这就是直觉排序(大端)。但我的平台使用的Endian表示很少,所以我的编译器将其视为

    0      1           00    010          1
       battery_ok           flags1  line_current_on

反之亦然。你的结构也是如此。请注意,位字段如何位于内存中
电压
成员之前。小尾端。

在具有8位字符(八位字节)和小尾端字节顺序的系统上(与所有x86/x64处理器一样),预期输出为17838,或十六进制
45AE


在具有8位字符(八位字节)和大端字节顺序的系统上,预期输出为44613,或十六进制
AE45

在具有不同大小字符的系统上,输出更难预测,但幸运的是,这些字符即使不是不存在的,也是罕见的


说明:内部结构有一个明确定义的顺序,后面是两个完整的八位组。因此,很明显,在您的代码之后,它们将依次包含十六进制值
AE
45
。它们被映射到一个
short
作为一个并集,本质上意味着将相同的内存数据作为另一种类型进行“重新定义”,而
short
被标准定义为一个2字节的值,这意味着如果您以这种方式读取它,它将起作用-第一个或最后一个字节是最重要的吗?因此,上面的预测结果仅在系统架构的这一部分有所不同。

为什么不运行此代码,自己看看呢?一个基本的?你的意思是这是考试的一部分吗?@sanjeevmk-因为运行代码和查看结果不可能告诉你它是定义良好的、实现定义的还是未定义的行为。@detly因此,我的答案如下。我刚刚指出,OP可以通过实验该代码、更改值等来更好地理解它。
printf(“状态:%hu”,myunion.Status)
BTW:main()应该返回int.@ChrisRow更新的答案,并给出解释。实际上,标准对位字段分配的规定比链接让您相信的要少得多。MSVC分配的位字段与GCC不同。如果你足够努力的话,我似乎记得有可能会注意到GCC分配它们的方式与Clang不同。等等…