【技巧】通过结构体进行的位操作


位域

通过定义相应位域的结构体指针,来访问变量的相应位域数据:

#include <stdio.h>

struct byte {//由低至高
	int a:4;
	int b:4;
	int c:4;
	int d:4;
}* p;

void main(){
	short int b =0xf1ff;
	p = (struct byte*)&b;
	printf("%d
",&b);	printf("%d
",p);//输出起始字节地址
	printf("%x
",p->c);//访问 b 的第 9 到第 12 位
}

输出:

1703724
1703724
1


一个小错误

将:

	short int b =0xf1ff;

改为:

	short int b =0xf8ff;
#include <stdio.h>

struct byte {//由低至高
	int a:4;
	int b:4;
	int c:4;
	int d:4;
}* p;

void main(){
	short int b =0xf8ff;
	p = (struct byte*)&b;
	printf("%d
",&b);	printf("%d
",p);//输出起始字节地址
	printf("%x
",p->c);//访问 b 的第 9 到第 12 位
}

输出不符合预期:

1703724
1703724
fffffff8

为什么?


若改为:

	short int b =0xf7ff;

输出正常:

1703724
1703724
7

为什么 7 正常,而 8 就出问题?
实际上 8 - F 都会有问题。


错误在结构体的定义中:

struct byte {//由低至高
	int a:4;
	int b:4;
	int c:4;
	int d:4;
};

8 的原码为 1 0 0 0,而 int 是 signed 类型,那么首位即为符号位。
符号位为 1 时转 int ,会在高位全部填充1,即 1111 1111 1111 1000,格式化%x输出即为 fffffff8。

而 7 的原码为 0 1 1 1,
符号位为 0 时转 int ,高位全部填充 0 ,也就是 0000 0000 0000 0111,格式化%x输出即为 7。

解决方法1:定义unsigned

struct byte {//由低至高
	unsigned int a:4;//可以不是int ,char ,long , long long等均可
	unsigned int b:4;//如果仅操作而不输出,float ,bool ,double等所有类型均可
	unsigned int c:4;
	unsigned int d:4;
};

解决方法2:输出时转类型

	printf("%x
",(unsigned int)p->c);
//其他类型也可,取决于程序员你的要求
原文地址:https://www.cnblogs.com/gaolihai/p/13149769.html