我正在尝试学习如何为包含位字段的联合分配内存。
我查看了与此类似的帖子和问题,并且了解到填充通常在大多数情况下取决于在结构中声明成员的顺序。
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
有人可以解释输出吗?仅仅是这种情况下的标准输出吗? 我在unbuntu中使用内置的gcc编译器
答案 0 :(得分:0)
您的编译器为联合中的位字段分配位的方式恰好与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
重叠,而不是低位位。同样,编译器为九位j
使用的存储单元大小可能与为两位i
使用的存储单元大小不同,在这种情况下,它们的位可能根本不重叠。 (例如,它可能对i
使用单个八位字节,而对j
使用32位字。八位字节将与32位字的某些部分重叠,但是不一定是用于j
的部分。)
答案 1 :(得分:0)
示例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。
这里是有趣的部分,例如i的类型为int。因此,第一位用于分配带符号的表示,大多数cpu以2的补码形式表示带符号的表示。 因此,如果我们反转1-1的2的补数,我们将获得值1。因此,我们得到的输出为-1。
Example2
#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的补码。