简体   繁体   English

C编程中的结构和联合

[英]Structures and Unions in C Programming

I am unsure what the Printf statement for Status would print ?, I am guessing it is compiler dependent, can anyone explain what this set Status at the end would print ? 我不确定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);
}

On a system with 8-bit chars (octets) and little endian byte orderings (like all x86/x64 processors) the expected output is 17838, or in hexadecimal 45AE . 在具有8位字符(八位字节)和低位字节序(如所有x86 / x64处理器)的系统上,预期输出为17838,或十六进制45AE

On a system with 8-bit chars (octets) and big endian byte orderings the expected output is 44613, or in hexadecimal AE45 . 在具有8位字符(八位字节)和大端字节序的系统上,预期输出为44613或十六进制AE45

On systems with differently sized chars the output is harder to predict, but luckily those are rare, if not non-existent, nowadays. 在具有不同大小的char的系统上,输出很难预测,但是幸运的是,如今这些罕见的(即使不是不存在的)也很少。

Explanation: the inner struct has a clearly defined ordering, following up 2 entire octets after eachother. 说明:内部结构具有明确定义的顺序,彼此依次跟随两个完整的八位位组。 Hence it is clear that after your code these will contain, in order, the hexadecimal values AE and 45 . 因此很明显,在您的代码之后,这些将按顺序包含十六进制值AE45 They are mapped onto a short as a union, essentially meaning a 'reintepretation' of the same in-memory data as another type, and a short is defined by standard as a 2-byte value, which means endianness comes into play if you read it out that way - is the first or the last byte the most significant? 它们作为联合映射到short ,本质上意味着与另一个类型相同的内存数据的“重新枚举”,并且short被标准定义为2字节值,这意味着如果您阅读,则字节顺序起作用这样子-第一个或最后一个字节最重要吗? Hence the predicted results above vary only on that part of the system's architecture. 因此,以上预测结果仅在系统体系结构的那部分上有所不同。

A Union can have variables with multiple data types, but you can assign values to only one of them. 联合可以具有具有多种数据类型的变量,但是您只能将值分配给其中之一。

What happens when you assign value to one variable, and print the another? 将值分配给一个变量并打印另一个变量时会发生什么?

You can think of a Union as a memory block, starting at address 0, for ease of calcualtion. 您可以将联合作为存储块,从地址0开始,以方便计算。 The size of this memory block, is the size of the largest data type used in this Union. 该存储块的大小是此联合中使用的最大数据类型的大小。 In your case, it would be the struct . 在您的情况下,它将是struct

So when you assign values to variables in the Union, you're "putting" values in this block. 因此,当您为Union中的变量分配值时,就是在此块中“放入”值。 And when you print any of those members , it'll print the contents of the block from the start of the Union upto the size of the data type of the member you printed. 而且,当您打印这些成员中的任何一个时,它将打印从联合会开始到所打印成员的数据类型大小的块内容。

In your case, you've printed the variable status . 就您而言,您已打印了变量status Now, on my system unsigned short uses 2 bytes of storage. 现在,在我的系统上, unsigned short使用2个字节的存储空间。 So on my system, it prints the first two bytes of the Union after you've assigned those values. 因此,在我的系统上,在分配了这些值之后,它会打印Union的前两个字节。 After assigning values like you did, the first two bytes of this memory block looks like this: 在像您一样分配值之后,此内存块的前两个字节如下所示:

    0100 0101 1010 1110

So , when I print status on my machine, it prints 0x45ae or 17838 in decimal. 因此,当我在计算机上打印status时,它将以十进制打印0x45ae17838 Thus, the result would vary from system to system, based on the value of sizeof(unsigned short) 因此,根据sizeof(unsigned short)的值,结果将因系统而异。

Play with that code, change the assigned values to notice the difference in output. 播放该代码,更改分配的值以注意到输出的差异。 That way you'd understand faster. 这样,您就会更快地了解。

Update: 更新:

The ordering of the bit field, depends on the target platform's endianness. 位字段的顺序取决于目标平台的字节序。 Check this out: 看一下这个:

Big and Little Endian 大端小端

and then, this: 然后,这:

How Endianness affects bitfield packing 字节序如何影响位域打包

With that in mind, here's the break up of your bitfield: 考虑到这一点,这是您的位域的分解:

    1                 010    00     1       0
   line_current_on   flags1     battery_ok

That's the intuitive ordering (big endian). 这就是直观的排序(大字节序)。 But my platform uses Little Endian representation, so my compiler looks at it as 但是我的平台使用Little Endian表示,所以我的编译器将其视为

    0      1           00    010          1
       battery_ok           flags1  line_current_on

which is the reverse. 相反。 Same goes for your struct. 同样适用于您的结构。 Notice how the bitfield came before the Voltage member in memory. 请注意位域如何出现在内存中的Voltage成员之前。 Little Endian. 小端。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM