繁体   English   中英

具有位域的工会成员的价值

[英]value of members of unions with bit-fields

我正在尝试学习如何为包含位字段的联合分配内存。

我查看了与此类似的帖子和问题,并且了解到填充在大多数情况下都取决于成员在结构中声明的顺序。

1。

union Example
{ int i:2;
  int j:9; 
};


int main(void)
{ 
   union Example ex;
   ex.j=15;
   printf("%d",ex.i);
}

输出:-1

2。

union Example
{ unsigned int i:2;
  int j:9; 
};


int main(void)
{ 
   union Example ex;
   ex.j=15;
   printf("%d",ex.i);
}

输出3

有人可以解释一下输出结果吗? 仅仅是这种情况下的标准输出吗? 我在ubuntu中使用内置的gcc编译器

你的编译器分配在工会位字段位的方式发生的低位重叠j用的比特i 因此,当j设置为15时, i的两位分别设置为1。

i是用int i:2声明的两位带符号整数时,编译器会将其解释为两位二进制的补码。 通过这种解释,比特11代表-1。

i是由unsigned int i:2声明的两位无符号整数时,它是纯二进制,没有符号位。 通过这种解释,位11代表3。

下面的程序显示,至少在您的C实现中,将有符号的两位整数设置为-1或将无符号的两位整数设置为3会在联合中产生相同的位模式。

#include <stdio.h>


int main(void)
{
    union Example
    {
        unsigned u;
        int i : 2;
        int j : 9;
        unsigned int k : 2;
    } ex;

    ex.u = 0;
    ex.i = -1;
    printf("ex.i = -1:  %#x.\n", ex.u);

    ex.u = 0;
    ex.j = 15;
    printf("ex.j = 15:  %#x.\n", ex.u);

    ex.u = 0;
    ex.k = 3;
    printf("ex.k =  3:  %#x.\n", ex.u);
}

输出:

ex.i = -1:  0x3.
ex.j = 15:  0xf.
ex.k =  3:  0x3.

请注意,编译器还可以从高到低而不是从低到高分配位,在这种情况下, j的高位将与i重叠,而不是低位。 同样,编译器为9位j使用的存储单元大小可能与为2位i使用的存储单元大小不同,在这种情况下,它们的位可能根本不重叠。 (例如,它可能对i使用单个8位字节,但对j使用32位字。这8位字节会与32位字的某些部分重叠,但不一定与j所用的部分重叠。 )

例1

#include <stdio.h>

union Example
{ int i:2;
  int j:9; 
};


int main(void)
{ 
   union Example ex;
   ex.j=15;
   printf("%d",ex.i);
   printf("\nSize of Union : %lu\n" , sizeof(ex));

   return 0;
}

输出:

-1
Size of Union : 4

观察结果:

从这个输出中,我们可以推断出,即使我们使用9位(最大值),编译器也会分配4字节(由于填充)。 声明union Example ex; 为联合示例对象ex分配4字节的内存。 语句ex.j=15; 将0x0000000F分配给该4字节的内存。 因此,对于j,它为9位分配0-0-0-0-0-1-1-1-1。 语句printf("%d",ex.i); 尝试打印ex.i(2位)。 从前面的语句中我们得到1-1。

有趣的部分到了,例如ex.i的类型为int。 因此,第一位用于分配带符号的表示,大多数cpu以2的补码形式表示带符号的表示。 因此,如果我们反转1-1的2的补数,我们将获得值1。因此,我们得到的输出为-1。

例2

#include <stdio.h>

union Example
{ unsigned int i:2;
  int j:9; 
};


int main(void)
{ 
   union Example ex;
   ex.j=15;
   printf("%d",ex.i);


   return 0;
}

输出:

3

观察结果:

声明union Example ex; 为联合示例对象ex分配4字节的内存。 语句ex.j=15; 将0x0000000F分配给该4字节的内存。 因此,对于j,它为9位分配0-0-0-0-0-1-1-1-1。 语句printf("%d",ex.i); 尝试打印ex.i(2位)。 从前面的语句中我们得到1-1。

与上述示例相同,但此处ex.i的类型为unsigned int。 因此,这里没有符号位用于表示。 因此,存储在2位位置中的是确切值。 因此输出为3。

希望我清除您的疑虑。 请在互联网上检查2和1的补码。

暂无
暂无

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

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