- 论坛徽章:
- 0
|
#include<stdio.h>
#include<stdlib.h>
int main(void)
{
union A{
char a;
char y:3;
char z:3;
char x:2;
}a;
a.a = 0x67;
printf("a.a =%0x a.x=%0x \t a.y=%0x\t a.z=%0x\n",a.a, a.x, a.y, a.z );
return 0;
}
结果
a.a =67 a.x=ffffffff a.y=ffffffff a.z=ffffffff
a.a =64 a.x=0 a.y=fffffffc a.z=fffffffc
a.a =65 a.x=1 a.y=fffffffd a.z=fffffffd
很久没动c语言了,很多基础性的东西都没有深入学习。今天看到关于联合体位域面试题,想了半天才知道程序答案的来由~~汗颜~~
如果单从位域来理解这个还是简单,问题的关键是理解其在计算机内的存取规则。
对a.a=64, 单从取位(二进制)上可知a.x=00, a.y=101, a.z=101.目前通用计算机x86大都是32位机,我的机器也是32位,在存取上默认是存取32位。对每个数而言第一位是符号位,补码存储。那么可以理解a.x的补码就是00000000, a.y的补码就是11111100, a.z的补码就是11111100.这样看比较自然,但如果输出结果是10进制,就会觉得难以理解。当然关键还是对数据的存取规则和编码的熟悉。
a.a=0x64的10进制结果是a.x=0, a.y=-4 ,a.z=-4
补充一点,union内的变量顺序对结果不影响(每次只可能有一种解释是合理的,这个跟struct显然不同)
关于位域在结构体的应用主要要注意内存对齐规则的理解和空域的理解
http://blog.csdn.net/jiyucn/archive/2006/07/01/862085.aspx
使用位域的主要目的是压缩存储,其大致规则为:
1) 如果相邻位域字段的类型相同,且其位宽之和小于类型的sizeof大小,则后面的字段将紧邻前一个字段存储,直到不能容纳为止;
2) 如果相邻位域字段的类型相同,但其位宽之和大于类型的sizeof大小,则后面的字段将从新的存储单元开始,其偏移量为其类型大小的整数倍;
3) 如果相邻的位域字段的类型不同,则各编译器的具体实现有差异,VC6采取不压缩方式,Dev-C++采取压缩方式;
4) 如果位域字段之间穿插着非位域字段,则不进行压缩;
5) 整个结构体的总大小为最宽基本类型成员大小的整数倍。
#include <stdio.h>
int main()
{
union
{
struct
{
unsigned short s1:3;
unsigned short s2:3;
unsigned short s3:3;
}x;
char c;
}v;
v.c=100;
printf("%d\n",sizeof(v));
printf("s1=%d\n",v.x.s1);
printf("s2=%d\n",v.x.s2);
printf("s3=%d\n",v.x.s3);
return 0;
}
fc6--linux下gcc-4.1.1
2
s1=4
s2=4
s3=5
windows xp2下vc6.0
2
s1=4
s2=4
s3=1
可见s3的结果并不一样vc6.0的结果如果只是按位取,就很好理解,这样跟之前的union的存取规则又不一样了~~而对于gcc-4.1.1,s3=5还没想出该结果的原因。同时考虑
struct
{
unsigned short s1:3;
unsigned short s2:3;
unsigned short s3:3;
unsigned short s4:7;
}x;
最后s4的结果更加扑朔迷离~~请大家多指点~·
[ 本帖最后由 fertiland 于 2007-5-17 10:51 编辑 ] |
|