2013-12-20 43 views
2

我不确定Printf语句是否会打印Status?,我猜测它是编译器相关的,任何人都可以解释这个设置状态在最后打印的是什么?C语言编程中的结构和联合

#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); 
} 
+5

为什么不运行此代码并亲自查看? –

+0

基本?你的意思是它是考试的一部分吗? –

+3

@sanjeevmk - 因为运行代码并查看结果无法告诉您它是否定义良好,实现定义或未定义行为。 – detly

回答

1

联合可以具有多种数据类型的变量,但您可以将值分配给其中的一个。

将值赋给一个变量并打印另一个变量会发生什么?

为了便于计算,您可以将联盟视为内存块,从地址0开始。该内存块的大小是本联盟中使用的最大数据类型的大小。在你的情况下,它将是struct

所以当你给Union中的变量赋值的时候,你会在这个块中“放”数值。当你打印任何这些成员时,它将打印从联盟开始的块的内容,直到你打印的成员的数据类型的大小。

就你而言,你已经打印了变量status。现在,在我的系统unsigned short使用2个字节的存储。所以在我的系统中,在分配这些值后,它会打印Union的前两个字节。像你这样分配值后,该内存块的前两个字节是这样的:

0100 0101 1010 1110 

所以,当我在我的机器上打印status,它打印在十进制0x45ae17838。因此,根据sizeof(unsigned short)

的值,结果会因系统而异,请使用该代码进行操作,更改指定的值以注意输出的差异。这样你会更快地理解。

更新:

位字段的顺序,取决于目标平台的字节序。检查了这一点:

Big and Little Endian

,然后,这一点:

How Endianness affects bitfield packing

考虑到这一点,这里的分手你的位域:

1     010 00  1  0 
    line_current_on flags1  battery_ok 

这是直观的排序(大端)。但我的平台使用小端的显示,所以我的编译器在它看来是

0  1   00 010   1 
     battery_ok   flags1 line_current_on 

是相反。你的结构也一样。请注意位域是如何在内存中的Voltage成员之前出现的。小尾巴。

+0

@ChrisRow更新答案和解释。 –

+1

实际上,该标准指定的位域分配要比链接http://mjfrazer.org/mjfrazer/bitfields/要少得多。 MSVC不同于GCC分配位域。如果有足够的努力,我似乎​​记得有可能注意到GCC与Clang不同地分配它们。等等… –

2

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

在具有8位字节(八位位组)和大端字节排序的系统上,期望的输出是44613,或者是十六进制的AE45

对于具有不同大小的字符的系统,输出很难预测,但幸运的是,如果不是现在不存在的话,这些很少见。

说明:内部结构有一个明确定义的顺序,在彼此之后跟随2个完整的八位字节。因此很显然,在您的代码之后,这些将依次包含十六进制值AE45。它们被映射到short上作为联合,基本上意味着与另一种类型相同的内存数据的“重新解释”,并且short由标准定义为2字节值,这意味着endianness在您读取时起作用它是这样 - 是最重要的第一个还是最后一个字节?因此,上述预测结果仅在系统体系结构的这一部分中有所不同。